From 95c9a995a161ead1135994b28acdb35f95a30d51 Mon Sep 17 00:00:00 2001
From: Sven Slootweg '.$text.'
+ To: {$to}
+ Subject: {$subject}
+
+ {$text}
+
+
", $text); + } + return $text; + } + + function mdwp_strip_p($t) { return preg_replace('{?p>}i', '', $t); } + + function mdwp_hide_tags($text) { + global $mdwp_hidden_tags, $mdwp_placeholders; + return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text); + } + function mdwp_show_tags($text) { + global $mdwp_hidden_tags, $mdwp_placeholders; + return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text); + } +} + + +### bBlog Plugin Info ### + +function identify_modifier_markdown() { + return array( + 'name' => 'markdown', + 'type' => 'modifier', + 'nicename' => 'PHP Markdown Extra', + 'description' => 'A text-to-HTML conversion tool for web writers', + 'authors' => 'Michel Fortin and John Gruber', + 'licence' => 'GPL', + 'version' => MARKDOWNEXTRA_VERSION, + 'help' => 'Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More...', + ); +} + + +### Smarty Modifier Interface ### + +function smarty_modifier_markdown($text) { + return Markdown($text); +} + + +### Textile Compatibility Mode ### + +# Rename this file to "classTextile.php" and it can replace Textile everywhere. + +if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) { + # Try to include PHP SmartyPants. Should be in the same directory. + @include_once 'smartypants.php'; + # Fake Textile class. It calls Markdown instead. + class Textile { + function TextileThis($text, $lite='', $encode='') { + if ($lite == '' && $encode == '') $text = Markdown($text); + if (function_exists('SmartyPants')) $text = SmartyPants($text); + return $text; + } + # Fake restricted version: restrictions are not supported for now. + function TextileRestricted($text, $lite='', $noimage='') { + return $this->TextileThis($text, $lite); + } + # Workaround to ensure compatibility with TextPattern 4.0.3. + function blockLite($text) { return $text; } + } +} + + + +# +# Markdown Parser Class +# + +class Markdown_Parser { + + ### Configuration Variables ### + + # Change to ">" for HTML output. + var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX; + var $tab_width = MARKDOWN_TAB_WIDTH; + + # Change to `true` to disallow markup or entities. + var $no_markup = false; + var $no_entities = false; + + # Predefined urls and titles for reference links and images. + var $predef_urls = array(); + var $predef_titles = array(); + + + ### Parser Implementation ### + + # Regex to match balanced [brackets]. + # Needed to insert a maximum bracked depth while converting to PHP. + var $nested_brackets_depth = 6; + var $nested_brackets_re; + + var $nested_url_parenthesis_depth = 4; + var $nested_url_parenthesis_re; + + # Table of hash values for escaped characters: + var $escape_chars = '\`*_{}[]()>#+-.!'; + var $escape_chars_re; + + + function Markdown_Parser() { + # + # Constructor function. Initialize appropriate member variables. + # + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + # Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + # Internal hashes used during transformation. + var $urls = array(); + var $titles = array(); + var $html_hashes = array(); + + # Status flag to avoid invalid nesting. + var $in_anchor = false; + + + function setup() { + # + # Called before the transformation process starts to setup parser + # states. + # + # Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + + $this->in_anchor = false; + } + + function teardown() { + # + # Called after the transformation process to clear any variable + # which may be taking up memory unnecessarly. + # + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + + function transform($text) { + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + var $document_gamut = array( + # Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + + "runBasicBlockGamut" => 30, + ); + + + function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; # String that will replace the block + } + + + function hashHTMLBlocks($text) { + if ($this->no_markup) return $text; + + $less_than_tab = $this->tab_width - 1; + + # Hashify HTML blocks: + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap
s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + # + # * List "a" is made of tags which can be both inline or block-level. + # These will be treated block-level when the start tag is alone on + # its line, otherwise they're not matched here and will be taken as + # inline later. + # * List "b" is made of tags which are always block-level; + # + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|form|fieldset|iframe|math|svg|'. + 'article|section|nav|aside|hgroup|header|footer|'. + 'figure'; + + # Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). # end of opening tag + '.*?'. # last level nested tag content + str_repeat(' + \2\s*> # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + # First, look for nested blocks, e.g.: + #
` blocks.
+ #
+ $text = preg_replace_callback('{
+ (?:\n\n|\A\n?)
+ ( # $1 = the code block -- one or more lines, starting with a space/tab
+ (?>
+ [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
+ .*\n+
+ )+
+ )
+ ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+ }xm',
+ array(&$this, '_doCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+ function _doCodeBlocks_callback($matches) {
+ $codeblock = $matches[1];
+
+ $codeblock = $this->outdent($codeblock);
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+
+ # trim leading newlines and trailing newlines
+ $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+ $codeblock = "$codeblock\n
";
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
+ }
+
+
+ function makeCodeSpan($code) {
+ #
+ # Create a code span markup for $code. Called from handleSpanToken.
+ #
+ $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+ return $this->hashPart("$code
");
+ }
+
+
+ var $em_relist = array(
+ '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) {
+ foreach ($this->strong_relist as $strong => $strong_re) {
+ # Construct list of allowed token expressions.
+ $token_relist = array();
+ if (isset($this->em_strong_relist["$em$strong"])) {
+ $token_relist[] = $this->em_strong_relist["$em$strong"];
+ }
+ $token_relist[] = $em_re;
+ $token_relist[] = $strong_re;
+
+ # Construct master expression from list.
+ $token_re = '{('. implode('|', $token_relist) .')}';
+ $this->em_strong_prepared_relist["$em$strong"] = $token_re;
+ }
+ }
+ }
+
+ function doItalicsAndBold($text) {
+ $token_stack = array('');
+ $text_stack = array('');
+ $em = '';
+ $strong = '';
+ $tree_char_em = false;
+
+ while (1) {
+ #
+ # Get prepared regular expression for seraching emphasis tokens
+ # in current context.
+ #
+ $token_re = $this->em_strong_prepared_relist["$em$strong"];
+
+ #
+ # Each loop iteration search for the next emphasis token.
+ # Each token is then passed to handleSpanToken.
+ #
+ $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+ $text_stack[0] .= $parts[0];
+ $token =& $parts[1];
+ $text =& $parts[2];
+
+ if (empty($token)) {
+ # Reached end of text span: empty stack without emitting.
+ # any more emphasis.
+ while ($token_stack[0]) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ }
+ break;
+ }
+
+ $token_len = strlen($token);
+ if ($tree_char_em) {
+ # Reached closing marker while inside a three-char emphasis.
+ if ($token_len == 3) {
+ # Three-char closing marker, close em and strong.
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "$span";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ $strong = '';
+ } else {
+ # Other closing marker: close one em or strong and
+ # change current token state to match the other
+ $token_stack[0] = str_repeat($token{0}, 3-$token_len);
+ $tag = $token_len == 2 ? "strong" : "em";
+ $span = $text_stack[0];
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span$tag>";
+ $text_stack[0] = $this->hashPart($span);
+ $$tag = ''; # $$tag stands for $em or $strong
+ }
+ $tree_char_em = false;
+ } else if ($token_len == 3) {
+ if ($em) {
+ # Reached closing marker for both em and strong.
+ # Closing strong marker:
+ for ($i = 0; $i < 2; ++$i) {
+ $shifted_token = array_shift($token_stack);
+ $tag = strlen($shifted_token) == 2 ? "strong" : "em";
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span$tag>";
+ $text_stack[0] .= $this->hashPart($span);
+ $$tag = ''; # $$tag stands for $em or $strong
+ }
+ } else {
+ # Reached opening three-char emphasis marker. Push on token
+ # stack; will be handled by the special condition above.
+ $em = $token{0};
+ $strong = "$em$em";
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $tree_char_em = true;
+ }
+ } else if ($token_len == 2) {
+ if ($strong) {
+ # Unwind any dangling emphasis marker:
+ if (strlen($token_stack[0]) == 1) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ }
+ # Closing strong marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "$span";
+ $text_stack[0] .= $this->hashPart($span);
+ $strong = '';
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $strong = $token;
+ }
+ } else {
+ # Here $token_len == 1
+ if ($em) {
+ if (strlen($token_stack[0]) == 1) {
+ # Closing emphasis marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "$span";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ } else {
+ $text_stack[0] .= $token;
+ }
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $em = $token;
+ }
+ }
+ }
+ return $text_stack[0];
+ }
+
+
+ function doBlockQuotes($text) {
+ $text = preg_replace_callback('/
+ ( # Wrap whole match in $1
+ (?>
+ ^[ ]*>[ ]? # ">" at the start of a line
+ .+\n # rest of the first line
+ (.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ )
+ /xm',
+ array(&$this, '_doBlockQuotes_callback'), $text);
+
+ return $text;
+ }
+ function _doBlockQuotes_callback($matches) {
+ $bq = $matches[1];
+ # trim one level of quoting - trim whitespace-only lines
+ $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+ $bq = $this->runBlockGamut($bq); # recurse
+
+ $bq = preg_replace('/^/m', " ", $bq);
+ # These leading spaces cause problem with content,
+ # so we need to fix that:
+ $bq = preg_replace_callback('{(\s*.+?
)}sx',
+ array(&$this, '_doBlockQuotes_callback2'), $bq);
+
+ return "\n". $this->hashBlock("\n$bq\n
")."\n\n";
+ }
+ function _doBlockQuotes_callback2($matches) {
+ $pre = $matches[1];
+ $pre = preg_replace('/^ /m', '', $pre);
+ return $pre;
+ }
+
+
+ function formParagraphs($text) {
+ #
+ # Params:
+ # $text - string to process with html tags
+ #
+ # Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ #
+ # Wrap
tags and unhashify HTML blocks
+ #
+ foreach ($grafs as $key => $value) {
+ if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+ # Is a paragraph.
+ $value = $this->runSpanGamut($value);
+ $value = preg_replace('/^([ ]*)/', "
", $value);
+ $value .= "
";
+ $grafs[$key] = $this->unhash($value);
+ }
+ else {
+ # Is a block.
+ # Modify elements of @grafs in-place...
+ $graf = $value;
+ $block = $this->html_hashes[$graf];
+ $graf = $block;
+// if (preg_match('{
+// \A
+// ( # $1 = tag
+// ]*
+// \b
+// markdown\s*=\s* ([\'"]) # $2 = attr quote char
+// 1
+// \2
+// [^>]*
+// >
+// )
+// ( # $3 = contents
+// .*
+// )
+// () # $4 = closing tag
+// \z
+// }xs', $block, $matches))
+// {
+// list(, $div_open, , $div_content, $div_close) = $matches;
+//
+// # We can't call Markdown(), because that resets the hash;
+// # that initialization code should be pulled into its own sub, though.
+// $div_content = $this->hashHTMLBlocks($div_content);
+//
+// # Run document gamut methods on the content.
+// foreach ($this->document_gamut as $method => $priority) {
+// $div_content = $this->$method($div_content);
+// }
+//
+// $div_open = preg_replace(
+// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+// }
+ $grafs[$key] = $graf;
+ }
+ }
+
+ return implode("\n\n", $grafs);
+ }
+
+
+ function encodeAttribute($text) {
+ #
+ # Encode text for a double-quoted HTML attribute. This function
+ # is *not* suitable for attributes enclosed in single quotes.
+ #
+ $text = $this->encodeAmpsAndAngles($text);
+ $text = str_replace('"', '"', $text);
+ return $text;
+ }
+
+
+ function encodeAmpsAndAngles($text) {
+ #
+ # Smart processing for ampersands and angle brackets that need to
+ # be encoded. Valid character entities are left alone unless the
+ # no-entities mode is set.
+ #
+ if ($this->no_entities) {
+ $text = str_replace('&', '&', $text);
+ } else {
+ # Ampersand-encoding based entirely on Nat Irons's Amputator
+ # MT plugin:
+ $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
+ '&', $text);;
+ }
+ # Encode remaining <'s
+ $text = str_replace('<', '<', $text);
+
+ return $text;
+ }
+
+
+ function doAutoLinks($text) {
+ $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
+ array(&$this, '_doAutoLinks_url_callback'), $text);
+
+ # Email addresses:
+ $text = preg_replace_callback('{
+ <
+ (?:mailto:)?
+ (
+ (?:
+ [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
+ |
+ ".*?"
+ )
+ \@
+ (?:
+ [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+ |
+ \[[\d.a-fA-F:]+\] # IPv4 & IPv6
+ )
+ )
+ >
+ }xi',
+ array(&$this, '_doAutoLinks_email_callback'), $text);
+
+ return $text;
+ }
+ function _doAutoLinks_url_callback($matches) {
+ $url = $this->encodeAttribute($matches[1]);
+ $link = "$url";
+ return $this->hashPart($link);
+ }
+ function _doAutoLinks_email_callback($matches) {
+ $address = $matches[1];
+ $link = $this->encodeEmailAddress($address);
+ return $this->hashPart($link);
+ }
+
+
+ function encodeEmailAddress($addr) {
+ #
+ # Input: an email address, e.g. "foo@example.com"
+ #
+ # Output: the email address as a mailto link, with each character
+ # of the address encoded as either a decimal or hex entity, in
+ # the hopes of foiling most address harvesting spam bots. E.g.:
+ #
+ #
+ #
+ # Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+ # With some optimizations by Milian Wolff.
+ #
+ $addr = "mailto:" . $addr;
+ $chars = preg_split('/(? $char) {
+ $ord = ord($char);
+ # Ignore non-ascii chars.
+ if ($ord < 128) {
+ $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+ # roughly 10% raw, 45% hex, 45% dec
+ # '@' *must* be encoded. I insist.
+ if ($r > 90 && $char != '@') /* do nothing */;
+ else if ($r < 45) $chars[$key] = ''.dechex($ord).';';
+ else $chars[$key] = ''.$ord.';';
+ }
+ }
+
+ $addr = implode('', $chars);
+ $text = implode('', array_slice($chars, 7)); # text without `mailto:`
+ $addr = "$text";
+
+ return $addr;
+ }
+
+
+ function parseSpan($str) {
+ #
+ # Take the string $str and parse it into tokens, hashing embeded HTML,
+ # escaped characters and handling code spans.
+ #
+ $output = '';
+
+ $span_re = '{
+ (
+ \\\\'.$this->escape_chars_re.'
+ |
+ (?no_markup ? '' : '
+ |
+ # comment
+ |
+ <\?.*?\?> | <%.*?%> # processing instruction
+ |
+ <[!$]?[-a-zA-Z0-9:_]+ # regular tags
+ (?>
+ \s
+ (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+ )?
+ >
+ |
+ <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag
+ |
+ [-a-zA-Z0-9:_]+\s*> # closing tag
+ ').'
+ )
+ }xs';
+
+ while (1) {
+ #
+ # Each loop iteration seach for either the next tag, the next
+ # openning code span marker, or the next escaped character.
+ # Each token is then passed to handleSpanToken.
+ #
+ $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ # Create token from text preceding tag.
+ if ($parts[0] != "") {
+ $output .= $parts[0];
+ }
+
+ # Check if we reach the end.
+ if (isset($parts[1])) {
+ $output .= $this->handleSpanToken($parts[1], $parts[2]);
+ $str = $parts[2];
+ }
+ else {
+ break;
+ }
+ }
+
+ return $output;
+ }
+
+
+ function handleSpanToken($token, &$str) {
+ #
+ # Handle $token provided by parseSpan by determining its nature and
+ # returning the corresponding value that should replace it.
+ #
+ switch ($token{0}) {
+ case "\\":
+ return $this->hashPart("". ord($token{1}). ";");
+ case "`":
+ # Search for end marker in remaining text.
+ if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
+ $str, $matches))
+ {
+ $str = $matches[2];
+ $codespan = $this->makeCodeSpan($matches[1]);
+ return $this->hashPart($codespan);
+ }
+ return $token; // return as text since no ending marker found.
+ default:
+ return $this->hashPart($token);
+ }
+ }
+
+
+ function outdent($text) {
+ #
+ # Remove one level of line-leading tabs or spaces
+ #
+ return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+ }
+
+
+ # String length function for detab. `_initDetab` will create a function to
+ # hanlde UTF-8 if the default function does not exist.
+ var $utf8_strlen = 'mb_strlen';
+
+ function detab($text) {
+ #
+ # Replace tabs with the appropriate amount of space.
+ #
+ # For each line we separate the line in blocks delemited by
+ # tab characters. Then we reconstruct every line by adding the
+ # appropriate number of space between each blocks.
+
+ $text = preg_replace_callback('/^.*\t.*$/m',
+ array(&$this, '_detab_callback'), $text);
+
+ return $text;
+ }
+ function _detab_callback($matches) {
+ $line = $matches[0];
+ $strlen = $this->utf8_strlen; # strlen function for UTF-8.
+
+ # Split in blocks.
+ $blocks = explode("\t", $line);
+ # Add each blocks to the line.
+ $line = $blocks[0];
+ unset($blocks[0]); # Do not add first block twice.
+ foreach ($blocks as $block) {
+ # Calculate amount of space, insert spaces, insert block.
+ $amount = $this->tab_width -
+ $strlen($line, 'UTF-8') % $this->tab_width;
+ $line .= str_repeat(" ", $amount) . $block;
+ }
+ return $line;
+ }
+ function _initDetab() {
+ #
+ # Check for the availability of the function in the `utf8_strlen` property
+ # (initially `mb_strlen`). If the function is not available, create a
+ # function that will loosely count the number of UTF-8 characters with a
+ # regular expression.
+ #
+ if (function_exists($this->utf8_strlen)) return;
+ $this->utf8_strlen = create_function('$text', 'return preg_match_all(
+ "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
+ $text, $m);');
+ }
+
+
+ function unhash($text) {
+ #
+ # Swap back in all the tags hashed by _HashHTMLBlocks.
+ #
+ return preg_replace_callback('/(.)\x1A[0-9]+\1/',
+ array(&$this, '_unhash_callback'), $text);
+ }
+ function _unhash_callback($matches) {
+ return $this->html_hashes[$matches[0]];
+ }
+
+}
+
+
+#
+# Markdown Extra Parser Class
+#
+
+class MarkdownExtra_Parser extends Markdown_Parser {
+
+ ### Configuration Variables ###
+
+ # Prefix for footnote ids.
+ var $fn_id_prefix = "";
+
+ # Optional title attribute for footnote links and backlinks.
+ var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+ var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+
+ # Optional class attribute for footnote links and backlinks.
+ var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+ var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+
+ # Optional class prefix for fenced code block.
+ var $code_class_prefix = MARKDOWN_CODE_CLASS_PREFIX;
+ # Class attribute for code blocks goes on the `code` tag;
+ # setting this to true will put attributes on the `pre` tag instead.
+ var $code_attr_on_pre = MARKDOWN_CODE_ATTR_ON_PRE;
+
+ # Predefined abbreviations.
+ var $predef_abbr = array();
+
+
+ ### Parser Implementation ###
+
+ function MarkdownExtra_Parser() {
+ #
+ # Constructor function. Initialize the parser object.
+ #
+ # Add extra escapable characters before parent constructor
+ # initialize the table.
+ $this->escape_chars .= ':|';
+
+ # Insert extra document, block, and span transformations.
+ # Parent constructor will do the sorting.
+ $this->document_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "stripFootnotes" => 15,
+ "stripAbbreviations" => 25,
+ "appendFootnotes" => 50,
+ );
+ $this->block_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "doTables" => 15,
+ "doDefLists" => 45,
+ );
+ $this->span_gamut += array(
+ "doFootnotes" => 5,
+ "doAbbreviations" => 70,
+ );
+
+ parent::Markdown_Parser();
+ }
+
+
+ # Extra variables used during extra transformations.
+ var $footnotes = array();
+ var $footnotes_ordered = array();
+ var $footnotes_ref_count = array();
+ var $footnotes_numbers = array();
+ var $abbr_desciptions = array();
+ var $abbr_word_re = '';
+
+ # Give the current footnote number.
+ var $footnote_counter = 1;
+
+
+ function setup() {
+ #
+ # Setting up Extra-specific variables.
+ #
+ parent::setup();
+
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->footnotes_ref_count = array();
+ $this->footnotes_numbers = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+ $this->footnote_counter = 1;
+
+ foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+ if ($this->abbr_word_re)
+ $this->abbr_word_re .= '|';
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ }
+ }
+
+ function teardown() {
+ #
+ # Clearing Extra-specific variables.
+ #
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->footnotes_ref_count = array();
+ $this->footnotes_numbers = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+
+ parent::teardown();
+ }
+
+
+ ### Extra Attribute Parser ###
+
+ # Expression to use to catch attributes (includes the braces)
+ var $id_class_attr_catch_re = '\{((?:[ ]*[#.][-_:a-zA-Z0-9]+){1,})[ ]*\}';
+ # Expression to use when parsing in a context when no capture is desired
+ var $id_class_attr_nocatch_re = '\{(?:[ ]*[#.][-_:a-zA-Z0-9]+){1,}[ ]*\}';
+
+ function doExtraAttributes($tag_name, $attr) {
+ #
+ # Parse attributes caught by the $this->id_class_attr_catch_re expression
+ # and return the HTML-formatted list of attributes.
+ #
+ # Currently supported attributes are .class and #id.
+ #
+ if (empty($attr)) return "";
+
+ # Split on components
+ preg_match_all('/[#.][-_:a-zA-Z0-9]+/', $attr, $matches);
+ $elements = $matches[0];
+
+ # handle classes and ids (only first id taken into account)
+ $classes = array();
+ $id = false;
+ foreach ($elements as $element) {
+ if ($element{0} == '.') {
+ $classes[] = substr($element, 1);
+ } else if ($element{0} == '#') {
+ if ($id === false) $id = substr($element, 1);
+ }
+ }
+
+ # compose attributes as string
+ $attr_str = "";
+ if (!empty($id)) {
+ $attr_str .= ' id="'.$id.'"';
+ }
+ if (!empty($classes)) {
+ $attr_str .= ' class="'.implode(" ", $classes).'"';
+ }
+ return $attr_str;
+ }
+
+
+ function stripLinkDefinitions($text) {
+ #
+ # Strips link definitions from text, stores the URLs and titles in
+ # hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: ^[id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ [ ]*
+ (?:
+ <(.+?)> # url = $2
+ |
+ (\S+?) # url = $3
+ )
+ [ ]*
+ \n? # maybe one newline
+ [ ]*
+ (?:
+ (?<=\s) # lookbehind for whitespace
+ ["(]
+ (.*?) # title = $4
+ [")]
+ [ ]*
+ )? # title is optional
+ (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
+ (?:\n+|\Z)
+ }xm',
+ array(&$this, '_stripLinkDefinitions_callback'),
+ $text);
+ return $text;
+ }
+ function _stripLinkDefinitions_callback($matches) {
+ $link_id = strtolower($matches[1]);
+ $url = $matches[2] == '' ? $matches[3] : $matches[2];
+ $this->urls[$link_id] = $url;
+ $this->titles[$link_id] =& $matches[4];
+ $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
+ return ''; # String that will replace the block
+ }
+
+
+ ### HTML Block Parser ###
+
+ # Tags that are always treated as block tags:
+ var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption';
+
+ # Tags treated as block tags only if the opening tag is alone on its line:
+ var $context_block_tags_re = 'script|noscript|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
+
+ # Tags where markdown="1" default to span mode:
+ var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+
+ # Tags which must not have their contents modified, no matter where
+ # they appear:
+ var $clean_tags_re = 'script|math|svg';
+
+ # Tags that do not need to be closed.
+ var $auto_close_tags_re = 'hr|img|param|source|track';
+
+
+ function hashHTMLBlocks($text) {
+ #
+ # Hashify HTML Blocks and "clean tags".
+ #
+ # We only want to do this for block-level HTML tags, such as headers,
+ # lists, and tables. That's because we still want to wrap s around
+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ # phrase emphasis, and spans. The list of tags we're looking for is
+ # hard-coded.
+ #
+ # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+ # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
+ # attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
+ # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+ # These two functions are calling each other. It's recursive!
+ #
+ if ($this->no_markup) return $text;
+
+ #
+ # Call the HTML-in-Markdown hasher.
+ #
+ list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+
+ return $text;
+ }
+ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
+ $enclosing_tag_re = '', $span = false)
+ {
+ #
+ # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+ #
+ # * $indent is the number of space to be ignored when checking for code
+ # blocks. This is important because if we don't take the indent into
+ # account, something like this (which looks right) won't work as expected:
+ #
+ #
+ #
+ # Hello World. <-- Is this a Markdown code block or text?
+ # <-- Is this a Markdown code block or a real tag?
+ #
+ #
+ # If you don't like this, just don't indent the tag on which
+ # you apply the markdown="1" attribute.
+ #
+ # * If $enclosing_tag_re is not empty, stops at the first unmatched closing
+ # tag with that name. Nested tags supported.
+ #
+ # * If $span is true, text inside must treated as span. So any double
+ # newline will be replaced by a single newline so that it does not create
+ # paragraphs.
+ #
+ # Returns an array of that form: ( processed text , remaining text )
+ #
+ if ($text === '') return array('', '');
+
+ # Regex to check for the presense of newlines around a block tag.
+ $newline_before_re = '/(?:^\n?|\n\n)*$/';
+ $newline_after_re =
+ '{
+ ^ # Start of text following the tag.
+ (?>[ ]*)? # Optional comment.
+ [ ]*\n # Must be followed by newline.
+ }xs';
+
+ # Regex to match any tag.
+ $block_tag_re =
+ '{
+ ( # $2: Capture whole tag.
+ ? # Any opening or closing tag.
+ (?> # Tag name.
+ '.$this->block_tags_re.' |
+ '.$this->context_block_tags_re.' |
+ '.$this->clean_tags_re.' |
+ (?!\s)'.$enclosing_tag_re.'
+ )
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ # CData Block
+ |
+ # Code span marker
+ `+
+ '. ( !$span ? ' # If not in span.
+ |
+ # Indented code block
+ (?: ^[ ]*\n | ^ | \n[ ]*\n )
+ [ ]{'.($indent+4).'}[^\n]* \n
+ (?>
+ (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+ )*
+ |
+ # Fenced code block marker
+ (?<= ^ | \n )
+ [ ]{0,'.($indent+3).'}~{3,}
+ [ ]*
+ (?:
+ \.?[-_:a-zA-Z0-9]+ # standalone class name
+ |
+ '.$this->id_class_attr_nocatch_re.' # extra attributes
+ )?
+ [ ]*
+ \n
+ ' : '' ). ' # End (if not is span).
+ )
+ }xs';
+
+
+ $depth = 0; # Current depth inside the tag tree.
+ $parsed = ""; # Parsed text that will be returned.
+
+ #
+ # Loop through every tag until we find the closing tag of the parent
+ # or loop until reaching the end of text if no parent tag specified.
+ #
+ do {
+ #
+ # Split the text using the first $tag_match pattern found.
+ # Text before pattern will be first in the array, text after
+ # pattern will be at the end, and between will be any catches made
+ # by the pattern.
+ #
+ $parts = preg_split($block_tag_re, $text, 2,
+ PREG_SPLIT_DELIM_CAPTURE);
+
+ # If in Markdown span mode, add a empty-string span-level hash
+ # after each newline to prevent triggering any block element.
+ if ($span) {
+ $void = $this->hashPart("", ':');
+ $newline = "$void\n";
+ $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+ }
+
+ $parsed .= $parts[0]; # Text before current tag.
+
+ # If end of $text has been reached. Stop loop.
+ if (count($parts) < 3) {
+ $text = "";
+ break;
+ }
+
+ $tag = $parts[1]; # Tag to handle.
+ $text = $parts[2]; # Remaining text after current tag.
+ $tag_re = preg_quote($tag); # For use in a regular expression.
+
+ #
+ # Check for: Code span marker
+ #
+ if ($tag{0} == "`") {
+ # Find corresponding end marker.
+ $tag_re = preg_quote($tag);
+ if (preg_match('{^(?>.+?|\n(?!\n))*?(?.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text,
+ $matches))
+ {
+ # End marker found: pass text unchanged until marker.
+ $parsed .= $tag . $matches[0];
+ $text = substr($text, strlen($matches[0]));
+ }
+ else {
+ # No end marker: just skip it.
+ $parsed .= $tag;
+ }
+ }
+ #
+ # Check for: Indented code block.
+ #
+ else if ($tag{0} == "\n" || $tag{0} == " ") {
+ # Indented code block: pass it unchanged, will be handled
+ # later.
+ $parsed .= $tag;
+ }
+ #
+ # Check for: Opening Block level tag or
+ # Opening Context Block tag (like ins and del)
+ # used as a block tag (tag is alone on it's line).
+ #
+ else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+ ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+ preg_match($newline_before_re, $parsed) &&
+ preg_match($newline_after_re, $text) )
+ )
+ {
+ # Need to parse tag and following text using the HTML parser.
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+
+ # Make sure it stays outside of any paragraph by adding newlines.
+ $parsed .= "\n\n$block_text\n\n";
+ }
+ #
+ # Check for: Clean tag (like script, math)
+ # HTML Comments, processing instructions.
+ #
+ else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ # Need to parse tag and following text using the HTML parser.
+ # (don't check for markdown attribute)
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+
+ $parsed .= $block_text;
+ }
+ #
+ # Check for: Tag with same name as enclosing tag.
+ #
+ else if ($enclosing_tag_re !== '' &&
+ # Same name as enclosing tag.
+ preg_match('{^?(?:'.$enclosing_tag_re.')\b}', $tag))
+ {
+ #
+ # Increase/decrease nested tag count.
+ #
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+
+ if ($depth < 0) {
+ #
+ # Going out of parent element. Clean up and break so we
+ # return to the calling function.
+ #
+ $text = $tag . $text;
+ break;
+ }
+
+ $parsed .= $tag;
+ }
+ else {
+ $parsed .= $tag;
+ }
+ } while ($depth >= 0);
+
+ return array($parsed, $text);
+ }
+ function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+ #
+ # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+ #
+ # * Calls $hash_method to convert any blocks.
+ # * Stops when the first opening tag closes.
+ # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+ # (it is not inside clean tags)
+ #
+ # Returns an array of that form: ( processed text , remaining text )
+ #
+ if ($text === '') return array('', '');
+
+ # Regex to match `markdown` attribute inside of a tag.
+ $markdown_attr_re = '
+ {
+ \s* # Eat whitespace before the `markdown` attribute
+ markdown
+ \s*=\s*
+ (?>
+ (["\']) # $1: quote delimiter
+ (.*?) # $2: attribute value
+ \1 # matching delimiter
+ |
+ ([^\s>]*) # $3: unquoted attribute value
+ )
+ () # $4: make $3 always defined (avoid warnings)
+ }xs';
+
+ # Regex to match any tag.
+ $tag_re = '{
+ ( # $2: Capture whole tag.
+ ? # Any opening or closing tag.
+ [\w:$]+ # Tag name.
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ # CData Block
+ )
+ }xs';
+
+ $original_text = $text; # Save original text in case of faliure.
+
+ $depth = 0; # Current depth inside the tag tree.
+ $block_text = ""; # Temporary text holder for current text.
+ $parsed = ""; # Parsed text that will be returned.
+
+ #
+ # Get the name of the starting tag.
+ # (This pattern makes $base_tag_name_re safe without quoting.)
+ #
+ if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+ $base_tag_name_re = $matches[1];
+
+ #
+ # Loop through every tag until we find the corresponding closing tag.
+ #
+ do {
+ #
+ # Split the text using the first $tag_match pattern found.
+ # Text before pattern will be first in the array, text after
+ # pattern will be at the end, and between will be any catches made
+ # by the pattern.
+ #
+ $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ if (count($parts) < 3) {
+ #
+ # End of $text reached with unbalenced tag(s).
+ # In that case, we return original text unchanged and pass the
+ # first character as filtered to prevent an infinite loop in the
+ # parent function.
+ #
+ return array($original_text{0}, substr($original_text, 1));
+ }
+
+ $block_text .= $parts[0]; # Text before current tag.
+ $tag = $parts[1]; # Tag to handle.
+ $text = $parts[2]; # Remaining text after current tag.
+
+ #
+ # Check for: Auto-close tag (like
)
+ # Comments and Processing Instructions.
+ #
+ if (preg_match('{^?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ # Just add the tag to the block as if it was text.
+ $block_text .= $tag;
+ }
+ else {
+ #
+ # Increase/decrease nested tag count. Only do so if
+ # the tag's name match base tag's.
+ #
+ if (preg_match('{^?'.$base_tag_name_re.'\b}', $tag)) {
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+ }
+
+ #
+ # Check for `markdown="1"` attribute and handle it.
+ #
+ if ($md_attr &&
+ preg_match($markdown_attr_re, $tag, $attr_m) &&
+ preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+ {
+ # Remove `markdown` attribute from opening tag.
+ $tag = preg_replace($markdown_attr_re, '', $tag);
+
+ # Check if text inside this tag must be parsed in span mode.
+ $this->mode = $attr_m[2] . $attr_m[3];
+ $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+ preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+
+ # Calculate indent before tag.
+ if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+ $strlen = $this->utf8_strlen;
+ $indent = $strlen($matches[1], 'UTF-8');
+ } else {
+ $indent = 0;
+ }
+
+ # End preceding block with this tag.
+ $block_text .= $tag;
+ $parsed .= $this->$hash_method($block_text);
+
+ # Get enclosing tag name for the ParseMarkdown function.
+ # (This pattern makes $tag_name_re safe without quoting.)
+ preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+ $tag_name_re = $matches[1];
+
+ # Parse the content using the HTML-in-Markdown parser.
+ list ($block_text, $text)
+ = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
+ $tag_name_re, $span_mode);
+
+ # Outdent markdown text.
+ if ($indent > 0) {
+ $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
+ $block_text);
+ }
+
+ # Append tag content to parsed text.
+ if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
+ else $parsed .= "$block_text";
+
+ # Start over with a new block.
+ $block_text = "";
+ }
+ else $block_text .= $tag;
+ }
+
+ } while ($depth > 0);
+
+ #
+ # Hash last block text that wasn't processed inside the loop.
+ #
+ $parsed .= $this->$hash_method($block_text);
+
+ return array($parsed, $text);
+ }
+
+
+ function hashClean($text) {
+ #
+ # Called whenever a tag must be hashed when a function inserts a "clean" tag
+ # in $text, it passes through this function and is automaticaly escaped,
+ # blocking invalid nested overlap.
+ #
+ return $this->hashPart($text, 'C');
+ }
+
+
+ function doAnchors($text) {
+ #
+ # Turn Markdown link shortcuts into XHTML tags.
+ #
+ if ($this->in_anchor) return $text;
+ $this->in_anchor = true;
+
+ #
+ # First, handle reference-style links: [link text] [id]
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+ )
+ }xs',
+ array(&$this, '_doAnchors_reference_callback'), $text);
+
+ #
+ # Next, inline-style links: [link text](url "optional title")
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(.+?)> # href = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # href = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # Title = $7
+ \6 # matching quote
+ [ \n]* # ignore any spaces/tabs between closing quote and )
+ )? # title is optional
+ \)
+ (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
+ )
+ }xs',
+ array(&$this, '_doAnchors_inline_callback'), $text);
+
+ #
+ # Last, handle reference-style shortcuts: [link text]
+ # These must come last in case you've also got [link text][1]
+ # or [link text](/foo)
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ([^\[\]]+) # link text = $2; can\'t contain [ or ]
+ \]
+ )
+ }xs',
+ array(&$this, '_doAnchors_reference_callback'), $text);
+
+ $this->in_anchor = false;
+ return $text;
+ }
+ function _doAnchors_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $matches[2];
+ $link_id =& $matches[3];
+
+ if ($link_id == "") {
+ # for shortcut links like [this][] or [this].
+ $link_id = $link_text;
+ }
+
+ # lower-case and turn embedded newlines into spaces
+ $link_id = strtolower($link_id);
+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+ if (isset($this->urls[$link_id])) {
+ $url = $this->urls[$link_id];
+ $url = $this->encodeAttribute($url);
+
+ $result = "titles[$link_id] ) ) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ if (isset($this->ref_attr[$link_id]))
+ $result .= $this->ref_attr[$link_id];
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text";
+ $result = $this->hashPart($result);
+ }
+ else {
+ $result = $whole_match;
+ }
+ return $result;
+ }
+ function _doAnchors_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $this->runSpanGamut($matches[2]);
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+ $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]);
+
+
+ $url = $this->encodeAttribute($url);
+
+ $result = "encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ $result .= $attr;
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text";
+
+ return $this->hashPart($result);
+ }
+
+
+ function doImages($text) {
+ #
+ # Turn Markdown image shortcuts into tags.
+ #
+ #
+ # First, handle reference-style labeled images: ![alt text][id]
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+
+ )
+ }xs',
+ array(&$this, '_doImages_reference_callback'), $text);
+
+ #
+ # Next, handle inline images: ![alt text](url "optional title")
+ # Don't forget: encode * and _
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+ \s? # One optional whitespace character
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(\S*)> # src url = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # src url = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # title = $7
+ \6 # matching quote
+ [ \n]*
+ )? # title is optional
+ \)
+ (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
+ )
+ }xs',
+ array(&$this, '_doImages_inline_callback'), $text);
+
+ return $text;
+ }
+ function _doImages_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($alt_text); # for shortcut links like ![this][].
+ }
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ if (isset($this->urls[$link_id])) {
+ $url = $this->encodeAttribute($this->urls[$link_id]);
+ $result = "titles[$link_id])) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ if (isset($this->ref_attr[$link_id]))
+ $result .= $this->ref_attr[$link_id];
+ $result .= $this->empty_element_suffix;
+ $result = $this->hashPart($result);
+ }
+ else {
+ # If there's no such link ID, leave intact:
+ $result = $whole_match;
+ }
+
+ return $result;
+ }
+ function _doImages_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+ $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]);
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ $url = $this->encodeAttribute($url);
+ $result = "encodeAttribute($title);
+ $result .= " title=\"$title\""; # $title already quoted
+ }
+ $result .= $attr;
+ $result .= $this->empty_element_suffix;
+
+ return $this->hashPart($result);
+ }
+
+
+ function doHeaders($text) {
+ #
+ # Redefined to add id and class attribute support.
+ #
+ # Setext-style headers:
+ # Header 1 {#header1}
+ # ========
+ #
+ # Header 2 {#header2 .class1 .class2}
+ # --------
+ #
+ $text = preg_replace_callback(
+ '{
+ (^.+?) # $1: Header text
+ (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
+ [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
+ }mx',
+ array(&$this, '_doHeaders_callback_setext'), $text);
+
+ # atx-style headers:
+ # # Header 1 {#header1}
+ # ## Header 2 {#header2}
+ # ## Header 2 with closing hashes ## {#header3.class1.class2}
+ # ...
+ # ###### Header 6 {.class2}
+ #
+ $text = preg_replace_callback('{
+ ^(\#{1,6}) # $1 = string of #\'s
+ [ ]*
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #\'s (not counted)
+ (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
+ [ ]*
+ \n+
+ }xm',
+ array(&$this, '_doHeaders_callback_atx'), $text);
+
+ return $text;
+ }
+ function _doHeaders_callback_setext($matches) {
+ if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+ return $matches[0];
+ $level = $matches[3]{0} == '=' ? 1 : 2;
+ $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2]);
+ $block = "".$this->runSpanGamut($matches[1])." ";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+ function _doHeaders_callback_atx($matches) {
+ $level = strlen($matches[1]);
+ $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3]);
+ $block = "".$this->runSpanGamut($matches[2])." ";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+
+ function doTables($text) {
+ #
+ # Form HTML tables.
+ #
+ $less_than_tab = $this->tab_width - 1;
+ #
+ # Find tables with leading pipe.
+ #
+ # | Header 1 | Header 2
+ # | -------- | --------
+ # | Cell 1 | Cell 2
+ # | Cell 3 | Cell 4
+ #
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ [|] # Optional leading pipe (present)
+ (.+) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ [ ]* # Allowed whitespace.
+ [|] .* \n # Row content.
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array(&$this, '_doTable_leadingPipe_callback'), $text);
+
+ #
+ # Find tables without leading pipe.
+ #
+ # Header 1 | Header 2
+ # -------- | --------
+ # Cell 1 | Cell 2
+ # Cell 3 | Cell 4
+ #
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ (\S.*[|].*) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ .* [|] .* \n # Row content
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array(&$this, '_DoTable_callback'), $text);
+
+ return $text;
+ }
+ function _doTable_leadingPipe_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ # Remove leading pipe for each row.
+ $content = preg_replace('/^ *[|]/m', '', $content);
+
+ return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+ }
+ function _doTable_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ # Remove any tailing pipes for each line.
+ $head = preg_replace('/[|] *$/m', '', $head);
+ $underline = preg_replace('/[|] *$/m', '', $underline);
+ $content = preg_replace('/[|] *$/m', '', $content);
+
+ # Reading alignement from header underline.
+ $separators = preg_split('/ *[|] */', $underline);
+ foreach ($separators as $n => $s) {
+ if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"';
+ else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+ else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"';
+ else $attr[$n] = '';
+ }
+
+ # Parsing span elements, including code spans, character escapes,
+ # and inline HTML tags, so that pipes inside those gets ignored.
+ $head = $this->parseSpan($head);
+ $headers = preg_split('/ *[|] */', $head);
+ $col_count = count($headers);
+ $attr = array_pad($attr, $col_count, '');
+
+ # Write column headers.
+ $text = "\n";
+ $text .= "\n";
+ $text .= "\n";
+ foreach ($headers as $n => $header)
+ $text .= " ".$this->runSpanGamut(trim($header))." \n";
+ $text .= " \n";
+ $text .= "\n";
+
+ # Split content by row.
+ $rows = explode("\n", trim($content, "\n"));
+
+ $text .= "\n";
+ foreach ($rows as $row) {
+ # Parsing span elements, including code spans, character escapes,
+ # and inline HTML tags, so that pipes inside those gets ignored.
+ $row = $this->parseSpan($row);
+
+ # Split row by cell.
+ $row_cells = preg_split('/ *[|] */', $row, $col_count);
+ $row_cells = array_pad($row_cells, $col_count, '');
+
+ $text .= "\n";
+ foreach ($row_cells as $n => $cell)
+ $text .= " ".$this->runSpanGamut(trim($cell))." \n";
+ $text .= " \n";
+ }
+ $text .= "\n";
+ $text .= "
";
+
+ return $this->hashBlock($text) . "\n";
+ }
+
+
+ function doDefLists($text) {
+ #
+ # Form HTML definition lists.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Re-usable pattern to match any entire dl list:
+ $whole_list_re = '(?>
+ ( # $1 = whole list
+ ( # $2
+ [ ]{0,'.$less_than_tab.'}
+ ((?>.*\S.*\n)+) # $3 = defined term
+ \n?
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ (?s:.+?)
+ ( # $4
+ \z
+ |
+ \n{2,}
+ (?=\S)
+ (?! # Negative lookahead for another term
+ [ ]{0,'.$less_than_tab.'}
+ (?: \S.*\n )+? # defined term
+ \n?
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ (?! # Negative lookahead for another definition
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ )
+ )
+ )'; // mx
+
+ $text = preg_replace_callback('{
+ (?>\A\n?|(?<=\n\n))
+ '.$whole_list_re.'
+ }mx',
+ array(&$this, '_doDefLists_callback'), $text);
+
+ return $text;
+ }
+ function _doDefLists_callback($matches) {
+ # Re-usable patterns to match list item bullets and number markers:
+ $list = $matches[1];
+
+ # Turn double returns into triple returns, so that we can make a
+ # paragraph for the last item in a list, if necessary:
+ $result = trim($this->processDefListItems($list));
+ $result = "\n" . $result . "\n
";
+ return $this->hashBlock($result) . "\n\n";
+ }
+
+
+ function processDefListItems($list_str) {
+ #
+ # Process the contents of a single definition list, splitting it
+ # into individual term and definition list items.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # trim trailing blank lines:
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+ # Process definition terms.
+ $list_str = preg_replace_callback('{
+ (?>\A\n?|\n\n+) # leading line
+ ( # definition terms = $1
+ [ ]{0,'.$less_than_tab.'} # leading whitespace
+ (?!\:[ ]|[ ]) # negative lookahead for a definition
+ # mark (colon) or more whitespace.
+ (?> \S.* \n)+? # actual term (not whitespace).
+ )
+ (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
+ # with a definition mark.
+ }xm',
+ array(&$this, '_processDefListItems_callback_dt'), $list_str);
+
+ # Process actual definitions.
+ $list_str = preg_replace_callback('{
+ \n(\n+)? # leading line = $1
+ ( # marker space = $2
+ [ ]{0,'.$less_than_tab.'} # whitespace before colon
+ \:[ ]+ # definition mark (colon)
+ )
+ ((?s:.+?)) # definition text = $3
+ (?= \n+ # stop at next definition mark,
+ (?: # next term or end of text
+ [ ]{0,'.$less_than_tab.'} \:[ ] |
+ | \z
+ )
+ )
+ }xm',
+ array(&$this, '_processDefListItems_callback_dd'), $list_str);
+
+ return $list_str;
+ }
+ function _processDefListItems_callback_dt($matches) {
+ $terms = explode("\n", trim($matches[1]));
+ $text = '';
+ foreach ($terms as $term) {
+ $term = $this->runSpanGamut(trim($term));
+ $text .= "\n" . $term . " ";
+ }
+ return $text . "\n";
+ }
+ function _processDefListItems_callback_dd($matches) {
+ $leading_line = $matches[1];
+ $marker_space = $matches[2];
+ $def = $matches[3];
+
+ if ($leading_line || preg_match('/\n{2,}/', $def)) {
+ # Replace marker with the appropriate whitespace indentation
+ $def = str_repeat(' ', strlen($marker_space)) . $def;
+ $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+ $def = "\n". $def ."\n";
+ }
+ else {
+ $def = rtrim($def);
+ $def = $this->runSpanGamut($this->outdent($def));
+ }
+
+ return "\n " . $def . " \n";
+ }
+
+
+ function doFencedCodeBlocks($text) {
+ #
+ # Adding the fenced code block syntax to regular Markdown:
+ #
+ # ~~~
+ # Code block
+ # ~~~
+ #
+ $less_than_tab = $this->tab_width;
+
+ $text = preg_replace_callback('{
+ (?:\n|\A)
+ # 1: Opening marker
+ (
+ ~{3,} # Marker: three tilde or more.
+ )
+ [ ]*
+ (?:
+ \.?([-_:a-zA-Z0-9]+) # 2: standalone class name
+ |
+ '.$this->id_class_attr_catch_re.' # 3: Extra attributes
+ )?
+ [ ]* \n # Whitespace and newline following marker.
+
+ # 4: Content
+ (
+ (?>
+ (?!\1 [ ]* \n) # Not a closing marker.
+ .*\n+
+ )+
+ )
+
+ # Closing marker.
+ \1 [ ]* \n
+ }xm',
+ array(&$this, '_doFencedCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+ function _doFencedCodeBlocks_callback($matches) {
+ $classname =& $matches[2];
+ $attrs =& $matches[3];
+ $codeblock = $matches[4];
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+ $codeblock = preg_replace_callback('/^\n+/',
+ array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+
+ if ($classname != "") {
+ if ($classname{0} == '.')
+ $classname = substr($classname, 1);
+ $attr_str = ' class="'.$this->code_class_prefix.$classname.'"';
+ } else {
+ $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs);
+ }
+ $pre_attr_str = $this->code_attr_on_pre ? $attr_str : '';
+ $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
+ $codeblock = "$codeblock
";
+
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
+ }
+ function _doFencedCodeBlocks_newlines($matches) {
+ return str_repeat("
empty_element_suffix",
+ strlen($matches[0]));
+ }
+
+
+ #
+ # Redefining emphasis markers so that emphasis by underscore does not
+ # work in the middle of a word.
+ #
+ var $em_relist = array(
+ '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags
+ #
+ # Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ #
+ # Wrap tags and unhashify HTML blocks
+ #
+ foreach ($grafs as $key => $value) {
+ $value = trim($this->runSpanGamut($value));
+
+ # Check if this should be enclosed in a paragraph.
+ # Clean tag hashes & block tag hashes are left alone.
+ $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+
+ if ($is_p) {
+ $value = "
$value
";
+ }
+ $grafs[$key] = $value;
+ }
+
+ # Join grafs in one text, then unhash HTML tags.
+ $text = implode("\n\n", $grafs);
+
+ # Finish by removing any tag hashes still present in $text.
+ $text = $this->unhash($text);
+
+ return $text;
+ }
+
+
+ ### Footnotes
+
+ function stripFootnotes($text) {
+ #
+ # Strips link definitions from text, stores the URLs and titles in
+ # hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: [^id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ ( # text = $2 (no blank lines allowed)
+ (?:
+ .+ # actual text
+ |
+ \n # newlines but
+ (?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+ (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
+ # by non-indented content
+ )*
+ )
+ }xm',
+ array(&$this, '_stripFootnotes_callback'),
+ $text);
+ return $text;
+ }
+ function _stripFootnotes_callback($matches) {
+ $note_id = $this->fn_id_prefix . $matches[1];
+ $this->footnotes[$note_id] = $this->outdent($matches[2]);
+ return ''; # String that will replace the block
+ }
+
+
+ function doFootnotes($text) {
+ #
+ # Replace footnote references in $text [^id] with a special text-token
+ # which will be replaced by the actual footnote marker in appendFootnotes.
+ #
+ if (!$this->in_anchor) {
+ $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+ }
+ return $text;
+ }
+
+
+ function appendFootnotes($text) {
+ #
+ # Append footnote list to text.
+ #
+ $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array(&$this, '_appendFootnotes_callback'), $text);
+
+ if (!empty($this->footnotes_ordered)) {
+ $text .= "\n\n";
+ $text .= "\n";
+ $text .= "
empty_element_suffix ."\n";
+ $text .= "\n\n";
+
+ $attr = " rev=\"footnote\"";
+ if ($this->fn_backlink_class != "") {
+ $class = $this->fn_backlink_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_backlink_title != "") {
+ $title = $this->fn_backlink_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ }
+ $num = 0;
+
+ while (!empty($this->footnotes_ordered)) {
+ $footnote = reset($this->footnotes_ordered);
+ $note_id = key($this->footnotes_ordered);
+ unset($this->footnotes_ordered[$note_id]);
+ $ref_count = $this->footnotes_ref_count[$note_id];
+ unset($this->footnotes_ref_count[$note_id]);
+ unset($this->footnotes[$note_id]);
+
+ $footnote .= "\n"; # Need to append newline before parsing.
+ $footnote = $this->runBlockGamut("$footnote\n");
+ $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array(&$this, '_appendFootnotes_callback'), $footnote);
+
+ $attr = str_replace("%%", ++$num, $attr);
+ $note_id = $this->encodeAttribute($note_id);
+
+ # Prepare backlink, multiple backlinks if multiple references
+ $backlink = "↩";
+ for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
+ $backlink .= " ↩";
+ }
+ # Add backlink to last paragraph; create new paragraph if needed.
+ if (preg_match('{$}', $footnote)) {
+ $footnote = substr($footnote, 0, -4) . " $backlink";
+ } else {
+ $footnote .= "\n\n$backlink
";
+ }
+
+ $text .= "- \n";
+ $text .= $footnote . "\n";
+ $text .= "
\n\n";
+ }
+
+ $text .= "
\n";
+ $text .= "";
+ }
+ return $text;
+ }
+ function _appendFootnotes_callback($matches) {
+ $node_id = $this->fn_id_prefix . $matches[1];
+
+ # Create footnote marker only if it has a corresponding footnote *and*
+ # the footnote hasn't been used by another marker.
+ if (isset($this->footnotes[$node_id])) {
+ $num =& $this->footnotes_numbers[$node_id];
+ if (!isset($num)) {
+ # Transfer footnote content to the ordered list and give it its
+ # number
+ $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+ $this->footnotes_ref_count[$node_id] = 1;
+ $num = $this->footnote_counter++;
+ $ref_count_mark = '';
+ } else {
+ $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
+ }
+
+ $attr = " rel=\"footnote\"";
+ if ($this->fn_link_class != "") {
+ $class = $this->fn_link_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_link_title != "") {
+ $title = $this->fn_link_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ }
+
+ $attr = str_replace("%%", $num, $attr);
+ $node_id = $this->encodeAttribute($node_id);
+
+ return
+ "".
+ "$num".
+ "";
+ }
+
+ return "[^".$matches[1]."]";
+ }
+
+
+ ### Abbreviations ###
+
+ function stripAbbreviations($text) {
+ #
+ # Strips abbreviations from text, stores titles in hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: [id]*: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
+ (.*) # text = $2 (no blank lines allowed)
+ }xm',
+ array(&$this, '_stripAbbreviations_callback'),
+ $text);
+ return $text;
+ }
+ function _stripAbbreviations_callback($matches) {
+ $abbr_word = $matches[1];
+ $abbr_desc = $matches[2];
+ if ($this->abbr_word_re)
+ $this->abbr_word_re .= '|';
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ return ''; # String that will replace the block
+ }
+
+
+ function doAbbreviations($text) {
+ #
+ # Find defined abbreviations in text and wrap them in elements.
+ #
+ if ($this->abbr_word_re) {
+ // cannot use the /x modifier because abbr_word_re may
+ // contain significant spaces:
+ $text = preg_replace_callback('{'.
+ '(?abbr_word_re.')'.
+ '(?![\w\x1A])'.
+ '}',
+ array(&$this, '_doAbbreviations_callback'), $text);
+ }
+ return $text;
+ }
+ function _doAbbreviations_callback($matches) {
+ $abbr = $matches[0];
+ if (isset($this->abbr_desciptions[$abbr])) {
+ $desc = $this->abbr_desciptions[$abbr];
+ if (empty($desc)) {
+ return $this->hashPart("$abbr");
+ } else {
+ $desc = $this->encodeAttribute($desc);
+ return $this->hashPart("$abbr");
+ }
+ } else {
+ return $matches[0];
+ }
+ }
+
+}
+
+
+/*
+
+PHP Markdown Extra
+==================
+
+Description
+-----------
+
+This is a PHP port of the original Markdown formatter written in Perl
+by John Gruber. This special "Extra" version of PHP Markdown features
+further enhancements to the syntax for making additional constructs
+such as tables and definition list.
+
+Markdown is a text-to-HTML filter; it translates an easy-to-read /
+easy-to-write structured text format into HTML. Markdown's text format
+is mostly similar to that of plain text email, and supports features such
+as headers, *emphasis*, code blocks, blockquotes, and links.
+
+Markdown's syntax is designed not as a generic markup language, but
+specifically to serve as a front-end to (X)HTML. You can use span-level
+HTML tags anywhere in a Markdown document, and you can use block level
+HTML tags (like and as well).
+
+For more information about Markdown's syntax, see:
+
+
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+
+
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output Markdown actually produced.
+
+
+Version History
+---------------
+
+See the readme file for detailed release notes for this version.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown & Extra
+Copyright (c) 2004-2013 Michel Fortin
+
+All rights reserved.
+
+Based on Markdown
+Copyright (c) 2003-2006 John Gruber
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name "Markdown" nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as
+is" and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed. In no event shall the copyright owner
+or contributors be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damages (including, but not limited to,
+procurement of substitute goods or services; loss of use, data, or
+profits; or business interruption) however caused and on any theory of
+liability, whether in contract, strict liability, or tort (including
+negligence or otherwise) arising in any way out of the use of this
+software, even if advised of the possibility of such damage.
+
+*/
+?>
diff --git a/public_html/lib/swiftmailer/classes/Swift.php b/public_html/lib/swiftmailer/classes/Swift.php
new file mode 100644
index 0000000..f113ca0
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift.php
@@ -0,0 +1,81 @@
+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/public_html/lib/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/public_html/lib/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
new file mode 100644
index 0000000..87b6428
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
@@ -0,0 +1,183 @@
+_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 integer
+ *
+ * @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->_filter($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();
+ }
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php b/public_html/lib/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php
new file mode 100644
index 0000000..5c16248
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php
@@ -0,0 +1,186 @@
+_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 integer $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 integer $byteOffset
+ *
+ * @return boolean
+ */
+ 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/public_html/lib/swiftmailer/classes/Swift/ByteStream/FileByteStream.php b/public_html/lib/swiftmailer/classes/Swift/ByteStream/FileByteStream.php
new file mode 100644
index 0000000..dd666b3
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ByteStream/FileByteStream.php
@@ -0,0 +1,222 @@
+_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 integer $length
+ *
+ * @return string
+ *
+ * @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);
+
+ return $bytes;
+ } else {
+ $this->_resetReadHandle();
+
+ return false;
+ }
+ }
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param integer $byteOffset
+ *
+ * @return boolean
+ */
+ public function setReadPointer($byteOffset)
+ {
+ if (isset($this->_reader)) {
+ $this->_seekReadStreamToPosition($byteOffset);
+ }
+ $this->_offset = $byteOffset;
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php b/public_html/lib/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php
new file mode 100644
index 0000000..f35f885
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php
@@ -0,0 +1,44 @@
+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/public_html/lib/swiftmailer/classes/Swift/CharacterReader.php b/public_html/lib/swiftmailer/classes/Swift/CharacterReader.php
new file mode 100644
index 0000000..df64d8a
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterReader.php
@@ -0,0 +1,69 @@
+
+ */
+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 integer $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return integer
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars);
+
+ /**
+ * Returns the mapType, see constants.
+ *
+ * @return integer
+ */
+ 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 integer $size
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ public function getInitialByteSize();
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
new file mode 100644
index 0000000..49d7398
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
@@ -0,0 +1,99 @@
+
+ */
+class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader
+{
+ /**
+ * The number of bytes in a single character.
+ *
+ * @var integer
+ */
+ private $_width;
+
+ /**
+ * Creates a new GenericFixedWidthReader using $width bytes per character.
+ *
+ * @param integer $width
+ */
+ public function __construct($width)
+ {
+ $this->_width = $width;
+ }
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param integer $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ 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 integer $size
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ public function getInitialByteSize()
+ {
+ return $this->_width;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php
new file mode 100644
index 0000000..18f3b04
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php
@@ -0,0 +1,85 @@
+"\x07F") { // Invalid char
+ $currentMap[$i+$startOffset]=$string[$i];
+ }
+ }
+
+ return $strlen;
+ }
+
+ /**
+ * Returns mapType
+ *
+ * @return integer 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 integer $size
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php
new file mode 100644
index 0000000..dd3a60f
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php
@@ -0,0 +1,181 @@
+
+ */
+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 integer $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return integer
+ */
+ 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 integer 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 integer $size
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/CharacterReaderFactory.php b/public_html/lib/swiftmailer/classes/Swift/CharacterReaderFactory.php
new file mode 100644
index 0000000..d653b81
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterReaderFactory.php
@@ -0,0 +1,28 @@
+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/public_html/lib/swiftmailer/classes/Swift/CharacterStream.php b/public_html/lib/swiftmailer/classes/Swift/CharacterStream.php
new file mode 100644
index 0000000..2946200
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterStream.php
@@ -0,0 +1,91 @@
+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 integer $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 integer $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 integer $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/public_html/lib/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php b/public_html/lib/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php
new file mode 100644
index 0000000..98aabab
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php
@@ -0,0 +1,277 @@
+
+ */
+
+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 integer
+ */
+ private $_datasSize = 0;
+
+ /**
+ * Map.
+ *
+ * @var mixed
+ */
+ private $_map;
+
+ /**
+ * Map Type.
+ *
+ * @var integer
+ */
+ private $_mapType = 0;
+
+ /**
+ * Number of characters in the stream.
+ *
+ * @var integer
+ */
+ private $_charCount = 0;
+
+ /**
+ * Position in the stream.
+ *
+ * @var integer
+ */
+ 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 integer $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 integer $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 integer $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/public_html/lib/swiftmailer/classes/Swift/ConfigurableSpool.php b/public_html/lib/swiftmailer/classes/Swift/ConfigurableSpool.php
new file mode 100644
index 0000000..58d5275
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ConfigurableSpool.php
@@ -0,0 +1,64 @@
+
+ *
+ * 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).
+ *
+ * @package Swift
+ * @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 integer $limit
+ */
+ public function setMessageLimit($limit)
+ {
+ $this->_message_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the maximum number of messages to send per flush.
+ *
+ * @return integer The limit
+ */
+ public function getMessageLimit()
+ {
+ return $this->_message_limit;
+ }
+
+ /**
+ * Sets the time limit (in seconds) per flush.
+ *
+ * @param integer $limit The limit
+ */
+ public function setTimeLimit($limit)
+ {
+ $this->_time_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the time limit (in seconds) per flush.
+ *
+ * @return integer The limit
+ */
+ public function getTimeLimit()
+ {
+ return $this->_time_limit;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/DependencyContainer.php b/public_html/lib/swiftmailer/classes/Swift/DependencyContainer.php
new file mode 100644
index 0000000..b717861
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/DependencyContainer.php
@@ -0,0 +1,373 @@
+_store);
+ }
+
+ /**
+ * Test if an item is registered in this container with the given name.
+ *
+ * @see register()
+ *
+ * @param string $itemName
+ *
+ * @return boolean
+ */
+ 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;
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/DependencyException.php b/public_html/lib/swiftmailer/classes/Swift/DependencyException.php
new file mode 100644
index 0000000..b3f0170
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/DependencyException.php
@@ -0,0 +1,28 @@
+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/public_html/lib/swiftmailer/classes/Swift/Encoder.php b/public_html/lib/swiftmailer/classes/Swift/Encoder.php
new file mode 100644
index 0000000..53e88b8
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Encoder.php
@@ -0,0 +1,29 @@
+= $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/public_html/lib/swiftmailer/classes/Swift/Encoder/QpEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Encoder/QpEncoder.php
new file mode 100644
index 0000000..61cf31b
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Encoder/QpEncoder.php
@@ -0,0 +1,286 @@
+ '=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 integer $firstLineOffset, optional
+ * @param integer $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);
+ }
+
+ // -- Protected methods
+
+ /**
+ * Encode the given byte array into a verbatim QP form.
+ *
+ * @param integer[] $bytes
+ * @param integer $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 integer $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/public_html/lib/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php b/public_html/lib/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php
new file mode 100644
index 0000000..37e30c1
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php
@@ -0,0 +1,86 @@
+_charStream = $charStream;
+ }
+
+ /**
+ * Takes an unencoded string and produces a string encoded according to
+ * RFC 2231 from it.
+ *
+ * @param string $string
+ * @param integer $firstLineOffset
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Encoding.php b/public_html/lib/swiftmailer/classes/Swift/Encoding.php
new file mode 100644
index 0000000..9639194
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Encoding.php
@@ -0,0 +1,66 @@
+lookup($key);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/CommandEvent.php b/public_html/lib/swiftmailer/classes/Swift/Events/CommandEvent.php
new file mode 100644
index 0000000..fa4f444
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/CommandEvent.php
@@ -0,0 +1,67 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Events/CommandListener.php b/public_html/lib/swiftmailer/classes/Swift/Events/CommandListener.php
new file mode 100644
index 0000000..6800904
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/CommandListener.php
@@ -0,0 +1,26 @@
+_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 boolean $cancel, optional
+ */
+ public function cancelBubble($cancel = true)
+ {
+ $this->_bubbleCancelled = $cancel;
+ }
+
+ /**
+ * Returns true if this Event will not bubble any further up the stack.
+ *
+ * @return boolean
+ */
+ public function bubbleCancelled()
+ {
+ return $this->_bubbleCancelled;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/ResponseEvent.php b/public_html/lib/swiftmailer/classes/Swift/Events/ResponseEvent.php
new file mode 100644
index 0000000..6b9117c
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/ResponseEvent.php
@@ -0,0 +1,68 @@
+_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 boolean
+ */
+ public function isValid()
+ {
+ return $this->_valid;
+ }
+
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/ResponseListener.php b/public_html/lib/swiftmailer/classes/Swift/Events/ResponseListener.php
new file mode 100644
index 0000000..a39ba43
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/ResponseListener.php
@@ -0,0 +1,26 @@
+_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 integer $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 integer
+ */
+ public function getResult()
+ {
+ return $this->_result;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/SendListener.php b/public_html/lib/swiftmailer/classes/Swift/Events/SendListener.php
new file mode 100644
index 0000000..bc914f5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/SendListener.php
@@ -0,0 +1,33 @@
+_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 boolean $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);
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeEvent.php b/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeEvent.php
new file mode 100644
index 0000000..d8b5316
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeEvent.php
@@ -0,0 +1,29 @@
+getSource();
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeListener.php b/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeListener.php
new file mode 100644
index 0000000..1555037
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/TransportChangeListener.php
@@ -0,0 +1,47 @@
+_exception = $ex;
+ }
+
+ /**
+ * Get the TransportException thrown.
+ *
+ * @return Swift_TransportException
+ */
+ public function getException()
+ {
+ return $this->_exception;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Events/TransportExceptionListener.php b/public_html/lib/swiftmailer/classes/Swift/Events/TransportExceptionListener.php
new file mode 100644
index 0000000..709abda
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Events/TransportExceptionListener.php
@@ -0,0 +1,26 @@
+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/public_html/lib/swiftmailer/classes/Swift/FileSpool.php b/public_html/lib/swiftmailer/classes/Swift/FileSpool.php
new file mode 100644
index 0000000..e458c07
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/FileSpool.php
@@ -0,0 +1,201 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages on the filesystem.
+ *
+ * @package Swift
+ * @author Fabien Potencier
+ * @author Xavier De Cock
+ */
+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 boolean
+ */
+ 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 integer $limit
+ */
+ public function setRetryLimit($limit)
+ {
+ $this->_retryLimit=$limit;
+ }
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return boolean
+ *
+ * @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 integer $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 integer The number of sent e-mail's
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+ {
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+
+ $failedRecipients = (array) $failedRecipients;
+ $count = 0;
+ $time = time();
+ foreach (new DirectoryIterator($this->_path) 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 integer $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/public_html/lib/swiftmailer/classes/Swift/FileStream.php b/public_html/lib/swiftmailer/classes/Swift/FileStream.php
new file mode 100644
index 0000000..567633e
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/FileStream.php
@@ -0,0 +1,26 @@
+setFile(
+ new Swift_ByteStream_FileByteStream($path)
+ );
+
+ return $image;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/InputByteStream.php b/public_html/lib/swiftmailer/classes/Swift/InputByteStream.php
new file mode 100644
index 0000000..ae81e5d
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/InputByteStream.php
@@ -0,0 +1,77 @@
+_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 integer $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 integer $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 boolean
+ */
+ 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]);
+ }
+
+ // -- Private methods
+
+ /**
+ * 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/public_html/lib/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php b/public_html/lib/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php
new file mode 100644
index 0000000..740897a
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php
@@ -0,0 +1,328 @@
+_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 integer $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 integer $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 boolean
+ */
+ 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]);
+ }
+ }
+
+ // -- Private methods
+
+ /**
+ * 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 integer $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/public_html/lib/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php b/public_html/lib/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php
new file mode 100644
index 0000000..f4f8adb
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php
@@ -0,0 +1,53 @@
+_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/public_html/lib/swiftmailer/classes/Swift/LoadBalancedTransport.php b/public_html/lib/swiftmailer/classes/Swift/LoadBalancedTransport.php
new file mode 100644
index 0000000..6eb3db7
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/LoadBalancedTransport.php
@@ -0,0 +1,47 @@
+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/public_html/lib/swiftmailer/classes/Swift/MailTransport.php b/public_html/lib/swiftmailer/classes/Swift/MailTransport.php
new file mode 100644
index 0000000..6c57939
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/MailTransport.php
@@ -0,0 +1,47 @@
+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/public_html/lib/swiftmailer/classes/Swift/Mailer.php b/public_html/lib/swiftmailer/classes/Swift/Mailer.php
new file mode 100644
index 0000000..b6703de
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mailer.php
@@ -0,0 +1,115 @@
+_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 integer
+ */
+ 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/public_html/lib/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php b/public_html/lib/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php
new file mode 100644
index 0000000..37e98da
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php
@@ -0,0 +1,57 @@
+_recipients = $recipients;
+ }
+
+ /**
+ * Returns true only if there are more recipients to send to.
+ *
+ * @return boolean
+ */
+ 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/public_html/lib/swiftmailer/classes/Swift/Mailer/RecipientIterator.php b/public_html/lib/swiftmailer/classes/Swift/Mailer/RecipientIterator.php
new file mode 100644
index 0000000..073bce1
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mailer/RecipientIterator.php
@@ -0,0 +1,34 @@
+ 'Foo') or ('foo@bar' => NULL)
+ *
+ * @return array
+ */
+ public function nextRecipient();
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/MemorySpool.php b/public_html/lib/swiftmailer/classes/Swift/MemorySpool.php
new file mode 100644
index 0000000..764b5aa
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/MemorySpool.php
@@ -0,0 +1,84 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in memory.
+ *
+ * @package Swift
+ * @author Fabien Potencier
+ */
+class Swift_MemorySpool implements Swift_Spool
+{
+ protected $messages = array();
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return boolean
+ */
+ 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 boolean 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 integer 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/public_html/lib/swiftmailer/classes/Swift/Message.php b/public_html/lib/swiftmailer/classes/Swift/Message.php
new file mode 100644
index 0000000..158ea25
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Message.php
@@ -0,0 +1,85 @@
+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
+ ));
+ }
+
+ public function __wakeup()
+ {
+ Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message');
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Mime/Attachment.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Attachment.php
new file mode 100644
index 0000000..faf358f
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Attachment.php
@@ -0,0 +1,155 @@
+setDisposition('attachment');
+ $this->setContentType('application/octet-stream');
+ $this->_mimeTypes = $mimeTypes;
+ }
+
+ /**
+ * Get the nesting level used for this attachment.
+ *
+ * Always returns {@link LEVEL_MIXED}.
+ *
+ * @return integer
+ */
+ 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 integer
+ */
+ public function getSize()
+ {
+ return $this->_getHeaderParameter('Content-Disposition', 'size');
+ }
+
+ /**
+ * Set the file size of this attachment.
+ *
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Mime/CharsetObserver.php b/public_html/lib/swiftmailer/classes/Swift/Mime/CharsetObserver.php
new file mode 100644
index 0000000..bfd41ed
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/CharsetObserver.php
@@ -0,0 +1,26 @@
+= $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/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
new file mode 100644
index 0000000..6a8ea68
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
@@ -0,0 +1,75 @@
+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 integer $firstLineOffset if first line needs to be shorter
+ * @param integer $maxLineLength 0 indicates the default length for this encoding
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return quoted_printable_encode($string);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php
new file mode 100644
index 0000000..a1df77b
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php
@@ -0,0 +1,167 @@
+_name = $name;
+ $this->_canonical = $canonical;
+ }
+
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param integer $firstLineOffset ignored
+ * @param integer $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 integer $firstLineOffset ignored
+ * @param integer $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)
+ {
+ }
+
+ // -- Private methods
+
+ /**
+ * A safer (but weaker) wordwrap for unicode.
+ *
+ * @param string $string
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
new file mode 100644
index 0000000..46d356c
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
@@ -0,0 +1,125 @@
+_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 integer $firstLineOffset
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
new file mode 100644
index 0000000..8f1f9b5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
@@ -0,0 +1,65 @@
+
+ */
+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/public_html/lib/swiftmailer/classes/Swift/Mime/EmbeddedFile.php b/public_html/lib/swiftmailer/classes/Swift/Mime/EmbeddedFile.php
new file mode 100644
index 0000000..05e06e2
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/EmbeddedFile.php
@@ -0,0 +1,47 @@
+setDisposition('inline');
+ $this->setId($this->getId());
+ }
+
+ /**
+ * Get the nesting level of this EmbeddedFile.
+ *
+ * Returns {@see LEVEL_RELATED}.
+ *
+ * @return integer
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_RELATED;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Mime/EncodingObserver.php b/public_html/lib/swiftmailer/classes/Swift/Mime/EncodingObserver.php
new file mode 100644
index 0000000..e7e6f20
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/EncodingObserver.php
@@ -0,0 +1,26 @@
+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/public_html/lib/swiftmailer/classes/Swift/Mime/Header.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Header.php
new file mode 100644
index 0000000..55d3ab8
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Header.php
@@ -0,0 +1,95 @@
+getName(), "\r\n");
+ mb_internal_encoding($old);
+
+ return $newstring;
+ }
+
+ return parent::encodeString($string, $firstLineOffset, $maxLineLength);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
new file mode 100644
index 0000000..c9bbe71
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
@@ -0,0 +1,67 @@
+_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 integer $firstLineOffset optional
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderFactory.php b/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderFactory.php
new file mode 100644
index 0000000..7cab133
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/HeaderFactory.php
@@ -0,0 +1,80 @@
+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 integer $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 boolean $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 boolean
+ */
+ 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 integer $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 boolean $condition
+ */
+ protected function clearCachedValueIf($condition)
+ {
+ if ($condition) {
+ $this->setCachedValue(null);
+ }
+ }
+
+ // -- Private methods
+
+ /**
+ * 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) {
+ $tokens = array_merge($tokens, $this->generateTokenLines($token));
+ }
+
+ 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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php
new file mode 100644
index 0000000..9127cc2
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php
@@ -0,0 +1,127 @@
+
+ *
+ *
+ *
+ * @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 integer $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 integer $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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php
new file mode 100644
index 0000000..1d00015
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php
@@ -0,0 +1,183 @@
+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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php
new file mode 100644
index 0000000..0fda5ae
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php
@@ -0,0 +1,358 @@
+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:
+ *
+ * setNameAddresses(array(
+ * 'chris@swiftmailer.org' => 'Chris Corbyn',
+ * 'mark@swiftmailer.org' //No associated personal name
+ * ));
+ * ?>
+ *
+ *
+ * @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:
+ *
+ * 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddressStrings());
+ * // array (
+ * // 0 => Chris Corbyn ,
+ * // 1 => Mark Corbyn
+ * // )
+ * ?>
+ *
+ *
+ * @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:
+ *
+ * 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddresses());
+ * // array (
+ * // chris@swiftmailer.org => Chris Corbyn,
+ * // mark@swiftmailer.org => Mark Corbyn
+ * // )
+ * ?>
+ *
+ *
+ * @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:
+ *
+ * setAddresses(
+ * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld')
+ * );
+ * ?>
+ *
+ *
+ * @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 boolean $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 boolean
+ */
+ protected function tokenNeedsEncoding($token)
+ {
+ return preg_match('/[,;]/', $token) || parent::tokenNeedsEncoding($token);
+ }
+
+ // -- Private methods
+
+ /**
+ * 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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php
new file mode 100644
index 0000000..3ef628c
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php
@@ -0,0 +1,265 @@
+_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;
+ }
+
+ // -- Protected methods
+
+ /**
+ * 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;
+ }
+
+ // -- Private methods
+
+ /**
+ * 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 boolean $encoded
+ * @param boolean $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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php
new file mode 100644
index 0000000..bfecf3f
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php
@@ -0,0 +1,146 @@
+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/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php
new file mode 100644
index 0000000..2de49b4
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php
@@ -0,0 +1,114 @@
+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/public_html/lib/swiftmailer/classes/Swift/Mime/Message.php b/public_html/lib/swiftmailer/classes/Swift/Mime/Message.php
new file mode 100644
index 0000000..bce3af3
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/Message.php
@@ -0,0 +1,225 @@
+ '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/public_html/lib/swiftmailer/classes/Swift/Mime/MimeEntity.php b/public_html/lib/swiftmailer/classes/Swift/Mime/MimeEntity.php
new file mode 100644
index 0000000..bc9f2ad
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/MimeEntity.php
@@ -0,0 +1,117 @@
+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 boolean
+ */
+ public function getDelSp()
+ {
+ return ($this->_getHeaderParameter('Content-Type', 'delsp') == 'yes')
+ ? true
+ : false;
+ }
+
+ /**
+ * Turn delsp on or off for this entity.
+ *
+ * @param boolean $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);
+ }
+
+ // -- Protected methods
+
+ /** 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, $charset, 'utf-8');
+ } 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/public_html/lib/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php b/public_html/lib/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php
new file mode 100644
index 0000000..95172ec
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php
@@ -0,0 +1,36 @@
+_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 integer|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);
+ }
+
+ // -- Private methods
+
+ /** Apply the charset to the Header */
+ private function _setHeaderCharset(Swift_Mime_Header $header)
+ {
+ if (isset($this->_charset)) {
+ $header->setCharset($this->_charset);
+ }
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php
new file mode 100644
index 0000000..e06f936
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php
@@ -0,0 +1,387 @@
+_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 integer $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 integer $index
+ *
+ * @return boolean
+ */
+ 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 integer $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 integer $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 integer $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();
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMessage.php b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMessage.php
new file mode 100644
index 0000000..b6a674b
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMessage.php
@@ -0,0 +1,655 @@
+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 integer $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 integer
+ */
+ 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 string
+ */
+ 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 and array should be used.
+ *
+ * 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 integer $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 integer
+ */
+ 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);
+ }
+ }
+
+ // -- Protected methods
+
+ /** @see Swift_Mime_SimpleMimeEntity::_getIdField() */
+ protected function _getIdField()
+ {
+ return 'Message-ID';
+ }
+
+ // -- Private methods
+
+ /** Turn the body of this message into a child of itself if needed */
+ private 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/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php
new file mode 100644
index 0000000..4c1df5c
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php
@@ -0,0 +1,857 @@
+ 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 = uniqid();
+ $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 integer
+ */
+ 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()
+ {
+ return $this->_headers->has($this->_getIdField()) ? current((array) $this->_getHeaderFieldModel($this->_getIdField())) : $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 integer
+ */
+ 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 integer $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 integer $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() . uniqid() . '_=_';
+ }
+
+ 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");
+ }
+ }
+
+ // -- Protected methods
+
+ /**
+ * 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 = time() . '.' . uniqid();
+ $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 methods
+
+ 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/public_html/lib/swiftmailer/classes/Swift/MimePart.php b/public_html/lib/swiftmailer/classes/Swift/MimePart.php
new file mode 100644
index 0000000..10a4f3c
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/MimePart.php
@@ -0,0 +1,61 @@
+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/public_html/lib/swiftmailer/classes/Swift/NullTransport.php b/public_html/lib/swiftmailer/classes/Swift/NullTransport.php
new file mode 100644
index 0000000..335c479
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/NullTransport.php
@@ -0,0 +1,40 @@
+
+ *
+ * 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.
+ *
+ * @package Swift
+ * @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/public_html/lib/swiftmailer/classes/Swift/OutputByteStream.php b/public_html/lib/swiftmailer/classes/Swift/OutputByteStream.php
new file mode 100644
index 0000000..2ff7449
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/OutputByteStream.php
@@ -0,0 +1,48 @@
+setThreshold($threshold);
+ $this->setSleepTime($sleep);
+ $this->_sleeper = $sleeper;
+ }
+
+ /**
+ * Set the number of emails to send before restarting.
+ *
+ * @param integer $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 integer $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 integer $seconds
+ */
+ public function sleep($seconds)
+ {
+ if (isset($this->_sleeper)) {
+ $this->_sleeper->sleep($seconds);
+ } else {
+ sleep($seconds);
+ }
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php
new file mode 100644
index 0000000..8794aac
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php
@@ -0,0 +1,166 @@
+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/public_html/lib/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php
new file mode 100644
index 0000000..3269c69
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php
@@ -0,0 +1,33 @@
+
+ * $replacements = array(
+ * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"),
+ * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y")
+ * )
+ *
+ *
+ * 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());
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php
new file mode 100644
index 0000000..1f1e443
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php
@@ -0,0 +1,70 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Plugins/Logger.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Logger.php
new file mode 100644
index 0000000..81c1d9b
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Logger.php
@@ -0,0 +1,38 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php
new file mode 100644
index 0000000..eb362ef
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php
@@ -0,0 +1,74 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php
new file mode 100644
index 0000000..c542169
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php
@@ -0,0 +1,60 @@
+_isHtml = $isHtml;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ if ($this->_isHtml) {
+ printf('%s%s%s', htmlspecialchars($entry, ENT_QUOTES), '
', PHP_EOL);
+ } else {
+ printf('%s%s', $entry, PHP_EOL);
+ }
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function clear()
+ {
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function dump()
+ {
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Plugins/MessageLogger.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/MessageLogger.php
new file mode 100644
index 0000000..35d5de5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/MessageLogger.php
@@ -0,0 +1,77 @@
+messages = array();
+ }
+
+ /**
+ * Get the message list
+ *
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * Get the message count
+ *
+ * @return integer 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/public_html/lib/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php
new file mode 100644
index 0000000..d241721
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php
@@ -0,0 +1,33 @@
+_host = $host;
+ $this->_port = $port;
+ $this->_crypto = $crypto;
+ }
+
+ /**
+ * Create a new PopBeforeSmtpPlugin for $host and $port.
+ *
+ * @param string $host
+ * @param integer $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 integer $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 Methods
+
+ 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/public_html/lib/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php
new file mode 100644
index 0000000..f4a4c5f
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php
@@ -0,0 +1,195 @@
+_recipient = $recipient;
+ $this->_whitelist = $whitelist;
+ }
+
+ /**
+ * Set the recipient of all messages.
+ *
+ * @param string $recipient
+ */
+ public function setRecipient($recipient)
+ {
+ $this->_recipient = $recipient;
+ }
+
+ /**
+ * Get the recipient of all messages.
+ *
+ * @return int
+ */
+ 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();
+
+ // save current recipients
+ $headers->addMailboxHeader('X-Swift-To', $message->getTo());
+ $headers->addMailboxHeader('X-Swift-Cc', $message->getCc());
+ $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc());
+
+ // Add hard coded recipient
+ $message->addTo($this->_recipient);
+
+ // Filter remaining headers against whitelist
+ $this->_filterHeaderSet($headers, 'To');
+ $this->_filterHeaderSet($headers, 'Cc');
+ $this->_filterHeaderSet($headers, 'Bcc');
+ }
+
+ /**
+ * 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 ($recipient === $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 methods
+
+ 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/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporter.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporter.php
new file mode 100644
index 0000000..0dfa22d
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporter.php
@@ -0,0 +1,34 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php
new file mode 100644
index 0000000..844e2a1
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php
@@ -0,0 +1,61 @@
+_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/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php
new file mode 100644
index 0000000..7b8c188
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php
@@ -0,0 +1,41 @@
+" . PHP_EOL;
+ echo "PASS " . $address . PHP_EOL;
+ echo "" . PHP_EOL;
+ flush();
+ } else {
+ echo "" . PHP_EOL;
+ echo "FAIL " . $address . PHP_EOL;
+ echo "" . PHP_EOL;
+ flush();
+ }
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Plugins/Sleeper.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Sleeper.php
new file mode 100644
index 0000000..c491f63
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Sleeper.php
@@ -0,0 +1,26 @@
+_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 integer $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();
+ }
+ }
+
+ // -- Private methods
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param integer $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 integer $timePassed
+ *
+ * @return int
+ */
+ private function _throttleMessagesPerMinute($timePassed)
+ {
+ $expectedDuration = $this->_messages / ($this->_rate / 60);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Plugins/Timer.php b/public_html/lib/swiftmailer/classes/Swift/Plugins/Timer.php
new file mode 100644
index 0000000..12dd09b
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Plugins/Timer.php
@@ -0,0 +1,26 @@
+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 boolean $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/public_html/lib/swiftmailer/classes/Swift/ReplacementFilterFactory.php b/public_html/lib/swiftmailer/classes/Swift/ReplacementFilterFactory.php
new file mode 100644
index 0000000..4b6eed5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/ReplacementFilterFactory.php
@@ -0,0 +1,28 @@
+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/public_html/lib/swiftmailer/classes/Swift/SignedMessage.php b/public_html/lib/swiftmailer/classes/Swift/SignedMessage.php
new file mode 100644
index 0000000..f96b210
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/SignedMessage.php
@@ -0,0 +1,161 @@
+
+ */
+class Swift_SignedMessage extends Swift_Message
+{
+ /**
+ * @var Swift_Signers_HeaderSigner[]
+ */
+ private $headerSigners = array();
+
+ /**
+ * @var Swift_Signers_BodySigner[]
+ */
+ private $bodySigners = array();
+
+ /**
+ * @var array
+ */
+ private $savedMessage = array();
+
+ /**
+ * Create a new Message.
+ *
+ * @param string $subject
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return Swift_SignedMessage
+ */
+ public static function newInstance($subject = null, $body = null, $contentType = null, $charset = null)
+ {
+ return new self($subject, $body, $contentType, $charset);
+ }
+
+ /**
+ * Attach a new signature handler to the message.
+ *
+ * @param Swift_Signer $signer
+ * @return Swift_SignedMessage
+ */
+ 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;
+ }
+
+ /**
+ * Get this message as a complete string.
+ *
+ * @return string
+ */
+ public function 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)
+ {
+ $this->saveMessage();
+ $this->doSign();
+
+ parent::toByteStream($is);
+ $this->restoreMessage();
+ }
+
+ 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());
+ }
+ }
+
+ protected function saveMessage()
+ {
+ $this->savedMessage = array('headers'=> array());
+ $this->savedMessage['body'] = $this->getBody();
+ $this->savedMessage['children'] = $this->getChildren();
+ }
+
+ 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);
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+
+ protected function restoreMessage()
+ {
+ $this->setBody($this->savedMessage['body']);
+ $this->setChildren($this->savedMessage['children']);
+
+ $this->restoreHeaders();
+ $this->savedMessage = array();
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signer.php b/public_html/lib/swiftmailer/classes/Swift/Signer.php
new file mode 100644
index 0000000..865f557
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signer.php
@@ -0,0 +1,22 @@
+
+ */
+interface Swift_Signer
+{
+ public function reset();
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signers/BodySigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/BodySigner.php
new file mode 100644
index 0000000..3a653a3
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/BodySigner.php
@@ -0,0 +1,35 @@
+
+ */
+interface Swift_Signers_BodySigner extends Swift_Signer
+{
+ /**
+ * Change the Swift_Signed_Message to apply the singing.
+ *
+ * @param Swift_Signed_Message $message
+ *
+ * @return Swift_Signers_BodySigner
+ */
+ public function signMessage(Swift_SignedMessage $message);
+
+ /**
+ * Return the list of header a signer might tamper
+ *
+ * @return array
+ */
+ public function getAlteredHeaders();
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signers/DKIMSigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/DKIMSigner.php
new file mode 100644
index 0000000..f01acc9
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/DKIMSigner.php
@@ -0,0 +1,666 @@
+
+ */
+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 boolean
+ */
+ 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 boolean
+ */
+ 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;
+ }
+
+ 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 => $el) {
+ if ($el == $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 ($this->len === true) {
+ $this->_showLen = true;
+ $this->_maxLen = PHP_INT_MAX;
+ } elseif ($this->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 boolean $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;
+ }
+
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha1':
+ $algorithm = 'sha1';
+ break;
+ case 'rsa-sha256':
+ $algorithm = 'sha256';
+ break;
+ }
+ if (openssl_sign($this->_headerCanonData, $signature, $this->_privateKey, $algorithm)) {
+ return $signature;
+ }
+
+ return '';
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signers/DomainKeySigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/DomainKeySigner.php
new file mode 100644
index 0000000..3d4a9ac
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/DomainKeySigner.php
@@ -0,0 +1,509 @@
+
+ */
+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 unknown_type
+ */
+ protected $_signerIdentity;
+
+ /**
+ * Must we embed signed headers?
+ *
+ * @var boolean
+ */
+ protected $_debugHeaders = false;
+
+ // work variables
+ /**
+ * Headers used to generate hash
+ *
+ * @var array
+ */
+ private $_signedHeaders = array();
+
+ /**
+ * If debugHeaders is set store debugDatas here
+ *
+ * @var string
+ */
+ private $_debugHeadersData = '';
+
+ /**
+ * Stores the signature header
+ *
+ * @var Swift_Mime_Headers_ParameterizedHeader
+ */
+ protected $_domainKeyHeader;
+
+ /**
+ * Hash Handler
+ *
+ * @var hash_ressource
+ */
+ 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;
+ }
+
+ /**
+ * 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 => $el) {
+ if ($el == $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 boolean $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)
+ {
+ echo $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 = '';
+ }
+
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ $sig2 = '';
+ openssl_sign($this->_canonData, $sig2, $this->_privateKey, 'sha1');
+ var_dump($this->_hash);
+ var_dump($this->_privateKey);
+ if (openssl_private_encrypt($this->_hash, $signature, $this->_privateKey)) {
+ var_dump($this->_canonData, base64_encode($sig2), base64_encode($signature));
+
+ return $sig2;
+ return $signature;
+ }
+
+ return '';
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signers/HeaderSigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/HeaderSigner.php
new file mode 100644
index 0000000..47091db
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/HeaderSigner.php
@@ -0,0 +1,67 @@
+
+ */
+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/public_html/lib/swiftmailer/classes/Swift/Signers/PeclDKIMSigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/PeclDKIMSigner.php
new file mode 100644
index 0000000..af45fd2
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/PeclDKIMSigner.php
@@ -0,0 +1,115 @@
+
+ */
+
+class Swift_Signer_PeclDKIMSigner extends Swift_Signers_DKIMSigner
+{
+ private $_peclLoaded = false;
+
+ private $_dkimHandler = null;
+
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ parent::__construct($privateKey, $domainName, $selector);
+ if (extension_loaded('dkim')) {
+ $this->_peclLoaded = true;
+ }
+ }
+
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ if (! $this->_peclLoaded) {
+ return parent::addSignature($headers);
+ } else {
+ dkim_eom($this->_dkimHandler);
+ $headers->addTextHeader('DKIM-Signature: ', dkim_getsighdr($this->_dkimHandler));
+ }
+
+ return $this;
+ }
+
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ if (! $this->_peclLoaded) {
+ return parent::setHeaders($headers);
+ }
+ //dkim_sign(privateKey, selector, domain[, header_canon[, body_canon[, sign_alg[, body_length]]]])
+ $bodyLen = $this->_bodyLen();
+ if (is_bool($bodyLen)) {
+ $bodyLen = - 1;
+ }
+ $hash = ($this->_hashAlgorithm == 'rsa-sha1') ? DKIM_SIGN_RSASHA1 : DKIM_SIGN_RSASHA256;
+ $bodyCanon = ($this->_bodyCanon == 'simple') ? DKIM_CANON_SIMPLE : DKIM_CANON_RELAXED;
+ $headerCanon = ($this->_headerCanon == 'simple') ? DKIM_CANON_SIMPLE : DKIM_CANON_RELAXED;
+ $this->_dkimHandler = dkim_sign($this->_privateKey, $this->_selector, $this->_domainName, $headerCanon, $bodyCanon, $hash, $bodyLen);
+
+ $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() != '') {
+ dkim_header($this->_dkimHandler, $header->toString());
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ public function startBody()
+ {
+ if (! $this->_peclLoaded) {
+ return parent::startBody();
+ }
+ dkim_eoh($this->_dkimHandler);
+
+ return $this;
+ }
+
+ public function endBody()
+ {
+ if (! $this->_peclLoaded) {
+ return parent::endBody();
+ }
+ dkim_eob($this->_dkimHandler);
+
+ return $this;
+ }
+
+ public function reset()
+ {
+ $this->_dkimHandler = null;
+ parent::reset();
+ }
+
+ // Protected
+
+ protected function _canonicalizeBody($string)
+ {
+ if (! $this->_peclLoaded) {
+ return parent::_canonicalizeBody($string);
+ }
+ dkim_body($this->_dkimHandler, $string);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Signers/SMimeSigner.php b/public_html/lib/swiftmailer/classes/Swift/Signers/SMimeSigner.php
new file mode 100644
index 0000000..47c0a3d
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Signers/SMimeSigner.php
@@ -0,0 +1,430 @@
+
+ */
+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 static($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 integer $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 integer $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 Boolean
+ */
+ public function isSignThenEncrypt()
+ {
+ return $this->signThenEncrypt;
+ }
+
+ /**
+ * Resets internal states.
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function reset()
+ {
+ return $this;
+ }
+
+ /**
+ * Change the Swift_SignedMessage to apply the singing.
+ *
+ * @param Swift_SignedMessage $message
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function signMessage(Swift_SignedMessage $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_SignedMessage $mimeEntity
+ */
+ protected function toSMimeByteStream(Swift_InputByteStream $inputStream, Swift_SignedMessage $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_SignedMessage $message
+ *
+ * @return Swift_Message
+ */
+ protected function createMessage(Swift_SignedMessage $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())) {
+ 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_SignedMessage.
+ *
+ * @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/public_html/lib/swiftmailer/classes/Swift/SmtpTransport.php b/public_html/lib/swiftmailer/classes/Swift/SmtpTransport.php
new file mode 100644
index 0000000..4fc750a
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/SmtpTransport.php
@@ -0,0 +1,53 @@
+createDependenciesFor('transport.smtp')
+ );
+
+ $this->setHost($host);
+ $this->setPort($port);
+ $this->setEncryption($security);
+ }
+
+ /**
+ * Create a new SmtpTransport instance.
+ *
+ * @param string $host
+ * @param integer $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/public_html/lib/swiftmailer/classes/Swift/Spool.php b/public_html/lib/swiftmailer/classes/Swift/Spool.php
new file mode 100644
index 0000000..981c178
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Spool.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for spools.
+ *
+ * @package Swift
+ * @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 boolean
+ */
+ public function isStarted();
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return boolean 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 integer The number of sent emails
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null);
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/SpoolTransport.php b/public_html/lib/swiftmailer/classes/Swift/SpoolTransport.php
new file mode 100644
index 0000000..8a135d4
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/SpoolTransport.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @package Swift
+ * @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/public_html/lib/swiftmailer/classes/Swift/StreamFilter.php b/public_html/lib/swiftmailer/classes/Swift/StreamFilter.php
new file mode 100644
index 0000000..8b887bf
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/StreamFilter.php
@@ -0,0 +1,36 @@
+_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 boolean
+ */
+ 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 integer $_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/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php b/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php
new file mode 100644
index 0000000..ca7454e
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php
@@ -0,0 +1,67 @@
+_search = $search;
+ $this->_replace = $replace;
+ }
+
+ /**
+ * Returns true if based on the buffer passed more bytes should be buffered.
+ *
+ * @param string $buffer
+ *
+ * @return boolean
+ */
+ 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/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
new file mode 100644
index 0000000..bb4af77
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
@@ -0,0 +1,46 @@
+_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/public_html/lib/swiftmailer/classes/Swift/SwiftException.php b/public_html/lib/swiftmailer/classes/Swift/SwiftException.php
new file mode 100644
index 0000000..f3bcbed
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/SwiftException.php
@@ -0,0 +1,28 @@
+_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 boolean
+ */
+ 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;
+ }
+
+ // -- Protected methods
+
+ /** 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 . '"'
+ )
+ );
+ }
+ }
+
+ /** 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);
+ }
+
+ return $response;
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
new file mode 100644
index 0000000..80b4712
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
@@ -0,0 +1,83 @@
+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/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
new file mode 100644
index 0000000..deca3a5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
@@ -0,0 +1,53 @@
+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/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
new file mode 100644
index 0000000..ffa9af3
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
@@ -0,0 +1,52 @@
+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/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php
new file mode 100644
index 0000000..40b0908
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php
@@ -0,0 +1,268 @@
+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 boolean
+ */
+ 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()
+ {
+ }
+
+ // -- Protected methods
+
+ /**
+ * 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/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php
new file mode 100644
index 0000000..0c6dc2e
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php
@@ -0,0 +1,37 @@
+.
+ *
+ * @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 boolean $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/public_html/lib/swiftmailer/classes/Swift/Transport/EsmtpTransport.php b/public_html/lib/swiftmailer/classes/Swift/Transport/EsmtpTransport.php
new file mode 100644
index 0000000..19e2d77
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/EsmtpTransport.php
@@ -0,0 +1,393 @@
+ '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 integer $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 integer $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);
+ }
+
+ // -- Protected methods
+
+ /** 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)
+ );
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Transport/FailoverTransport.php b/public_html/lib/swiftmailer/classes/Swift/Transport/FailoverTransport.php
new file mode 100644
index 0000000..d0d3f69
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/FailoverTransport.php
@@ -0,0 +1,90 @@
+_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 methods
+
+ 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/public_html/lib/swiftmailer/classes/Swift/Transport/IoBuffer.php b/public_html/lib/swiftmailer/classes/Swift/Transport/IoBuffer.php
new file mode 100644
index 0000000..7559ebf
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/IoBuffer.php
@@ -0,0 +1,69 @@
+_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 boolean
+ */
+ 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);
+ }
+ }
+
+ // -- Protected methods
+
+ /**
+ * 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/public_html/lib/swiftmailer/classes/Swift/Transport/MailInvoker.php b/public_html/lib/swiftmailer/classes/Swift/Transport/MailInvoker.php
new file mode 100644
index 0000000..a9bff69
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/MailInvoker.php
@@ -0,0 +1,34 @@
+_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);
+ }
+
+ // -- Private methods
+
+ /** 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/public_html/lib/swiftmailer/classes/Swift/Transport/NullTransport.php b/public_html/lib/swiftmailer/classes/Swift/Transport/NullTransport.php
new file mode 100644
index 0000000..ce136d3
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/NullTransport.php
@@ -0,0 +1,88 @@
+
+ *
+ * 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.
+ *
+ * @package Swift
+ * @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 boolean
+ */
+ 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 integer 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');
+ }
+
+ return 0;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Transport/SendmailTransport.php b/public_html/lib/swiftmailer/classes/Swift/Transport/SendmailTransport.php
new file mode 100644
index 0000000..95c2e4a
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/SendmailTransport.php
@@ -0,0 +1,163 @@
+ 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 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' . $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;
+ }
+
+ // -- Protected methods
+
+ /** Get the params to initialize the buffer */
+ protected function _getBufferParams()
+ {
+ return $this->_params;
+ }
+}
diff --git a/public_html/lib/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php b/public_html/lib/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php
new file mode 100644
index 0000000..91157e5
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @package Swift
+ * @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 boolean
+ */
+ 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 integer 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/public_html/lib/swiftmailer/classes/Swift/Transport/StreamBuffer.php b/public_html/lib/swiftmailer/classes/Swift/Transport/StreamBuffer.php
new file mode 100644
index 0000000..c42ee00
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/Transport/StreamBuffer.php
@@ -0,0 +1,315 @@
+_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 integer $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 integer $length
+ *
+ * @return string|boolean
+ *
+ * @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)
+ {
+ }
+
+ // -- Protected methods
+
+ /** 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)
+ && fwrite($this->_in, $bytes))
+ {
+ return ++$this->_sequence;
+ }
+ }
+
+ // -- Private methods
+
+ /**
+ * 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/public_html/lib/swiftmailer/classes/Swift/TransportException.php b/public_html/lib/swiftmailer/classes/Swift/TransportException.php
new file mode 100644
index 0000000..48e41d1
--- /dev/null
+++ b/public_html/lib/swiftmailer/classes/Swift/TransportException.php
@@ -0,0 +1,29 @@
+
+ */
+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 boolean
+ */
+ public static function email($email)
+ {
+ if (self::$grammar===null) {
+ self::$grammar = Swift_DependencyContainer::getInstance()
+ ->lookup('mime.grammar');
+ }
+
+ return preg_match(
+ '/^' . self::$grammar->getDefinition('addr-spec') . '$/D',
+ $email
+ );
+ }
+}
diff --git a/public_html/lib/swiftmailer/dependency_maps/cache_deps.php b/public_html/lib/swiftmailer/dependency_maps/cache_deps.php
new file mode 100644
index 0000000..e49e8b8
--- /dev/null
+++ b/public_html/lib/swiftmailer/dependency_maps/cache_deps.php
@@ -0,0 +1,23 @@
+ 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/public_html/lib/swiftmailer/dependency_maps/message_deps.php b/public_html/lib/swiftmailer/dependency_maps/message_deps.php
new file mode 100644
index 0000000..272cb3a
--- /dev/null
+++ b/public_html/lib/swiftmailer/dependency_maps/message_deps.php
@@ -0,0 +1,9 @@
+ register('message.message')
+ -> asNewInstanceOf('Swift_Message')
+
+ -> register('message.mimepart')
+ -> asNewInstanceOf('Swift_MimePart')
+;
diff --git a/public_html/lib/swiftmailer/dependency_maps/mime_deps.php b/public_html/lib/swiftmailer/dependency_maps/mime_deps.php
new file mode 100644
index 0000000..25cd94d
--- /dev/null
+++ b/public_html/lib/swiftmailer/dependency_maps/mime_deps.php
@@ -0,0 +1,122 @@
+ 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.qpcontentencoder')
+ -> asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder')
+ -> withDependencies(array('mime.charstream', 'mime.bytecanonicalizer'))
+
+ -> register('mime.rawcontentencoder')
+ -> asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder')
+
+ -> register('mime.nativeqpcontentencoder')
+ -> asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder')
+
+ -> 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
+if (version_compare(phpversion(), '5.4.7', '>=')) {
+ Swift_DependencyContainer::getInstance()
+ ->register('mime.qpcontentencoder')
+ ->asAliasOf('mime.nativeqpcontentencoder')
+ ;
+}
+
+unset($swift_mime_types);
diff --git a/public_html/lib/swiftmailer/dependency_maps/transport_deps.php b/public_html/lib/swiftmailer/dependency_maps/transport_deps.php
new file mode 100644
index 0000000..f969932
--- /dev/null
+++ b/public_html/lib/swiftmailer/dependency_maps/transport_deps.php
@@ -0,0 +1,68 @@
+ 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'
+ )
+ ))
+
+ -> 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.eventdispatcher')
+ -> asNewInstanceOf('Swift_Events_SimpleEventDispatcher')
+
+ -> register('transport.replacementfactory')
+ -> asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory')
+;
diff --git a/public_html/lib/swiftmailer/mime_types.php b/public_html/lib/swiftmailer/mime_types.php
new file mode 100644
index 0000000..3baebb2
--- /dev/null
+++ b/public_html/lib/swiftmailer/mime_types.php
@@ -0,0 +1,76 @@
+ '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'
+);
diff --git a/public_html/lib/swiftmailer/preferences.php b/public_html/lib/swiftmailer/preferences.php
new file mode 100644
index 0000000..91b313b
--- /dev/null
+++ b/public_html/lib/swiftmailer/preferences.php
@@ -0,0 +1,29 @@
+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)) {
+ Swift_Preferences::getInstance()
+ ->setTempDir($tmp)
+ ->setCacheType('disk');
+} elseif (function_exists('sys_get_temp_dir') && @is_writable(sys_get_temp_dir())) {
+ Swift_Preferences::getInstance()
+ ->setTempDir(sys_get_temp_dir())
+ ->setCacheType('disk');
+}
+
+Swift_Preferences::getInstance()->setQPDotEscape(false);
diff --git a/public_html/lib/swiftmailer/swift_init.php b/public_html/lib/swiftmailer/swift_init.php
new file mode 100644
index 0000000..5897e6f
--- /dev/null
+++ b/public_html/lib/swiftmailer/swift_init.php
@@ -0,0 +1,28 @@
+ $router->uParameters[1], ":ActivationKey" => $router->uParameters[2]), 0, true);
+ $sUser->uIsActivated = true;
+ $sUser->InsertIntoDatabase();
+
+ $sUser->Authenticate();
+
+ flash_notice("Your account was successfully activated. Welcome on board!");
+ redirect("/");
+}
+catch (NotFoundException $e)
+{
+ /* No user or subscription with this e-mail address and verification key exists. Bail out.
+ * We'll throw a RouterException so that we only have to deal with 404s in one place. */
+ throw new RouterException("Confirmation key not found.");
+}
diff --git a/public_html/modules/account/login.php b/public_html/modules/account/login.php
new file mode 100644
index 0000000..cebd87c
--- /dev/null
+++ b/public_html/modules/account/login.php
@@ -0,0 +1,64 @@
+ $_POST['username']), 0, true);
+
+ if($sUser->VerifyPassword($_POST['password']))
+ {
+ if($sUser->sIsBanned == false)
+ {
+ $sUser->Authenticate();
+ flash_notice("Welcome back, {$sUser->sUsername}!");
+ redirect("/");
+ }
+ else
+ {
+ flash_error("You are banned from using this site.");
+ }
+ }
+ else
+ {
+ flash_error("The password you entered is incorrect. Did you forget your password?");
+ }
+ }
+ catch (NotFoundException $e)
+ {
+ flash_error("That username does not exist.");
+ }
+ }
+}
+
+$sPageContents = NewTemplater::Render("login", $locale->strings, array());
+$sPageTitle = "Log in";
diff --git a/public_html/modules/account/logout.php b/public_html/modules/account/logout.php
new file mode 100644
index 0000000..cad4d31
--- /dev/null
+++ b/public_html/modules/account/logout.php
@@ -0,0 +1,29 @@
+uParameters[1];
+
+if(!empty($_SESSION['logout_key']) && $_SESSION['logout_key'] == $uLogoutKey)
+{
+ unset($_SESSION['user_id']);
+ unset($_SESSION['logout_key']);
+
+ flash_notice("You have been logged out.");
+ redirect("/");
+}
+else
+{
+ throw new RouterException("No valid logout key specified.");
+}
diff --git a/public_html/modules/account/signup.php b/public_html/modules/account/signup.php
new file mode 100644
index 0000000..f5d4486
--- /dev/null
+++ b/public_html/modules/account/signup.php
@@ -0,0 +1,80 @@
+forget your password?");
+ }
+
+ if(empty($_POST['password']) || strlen($_POST['password']) < 8)
+ {
+ flash_error("You did not enter a valid password. Your password has to be at least 8 characters.");
+ }
+ elseif(empty($_POST['password2']) || $_POST['password'] != $_POST['password2'])
+ {
+ flash_error("The passwords you entered did not match.");
+ }
+
+ if(count(get_errors(false)) == 0)
+ {
+ $sUser = new User(0);
+ $sUser->uUsername = $_POST['username'];
+ $sUser->uPassword = $_POST['password'];
+ $sUser->uEmailAddress = $_POST['email'];
+ $sUser->uActivationKey = random_string(16);
+ $sUser->GenerateSalt();
+ $sUser->GenerateHash();
+ $sUser->InsertIntoDatabase();
+
+ send_mail($_POST['email'], "Please confirm your registration at BoxOnABudget.",
+ NewTemplater::Render("email/signup.txt", $locale->strings, array(
+ "confirmation-url" => "http://boxonabudget.com/account/confirm/{$sUser->sEmailAddress}/{$sUser->sActivationKey}/",
+ "name" => $sUser->uUsername)), /* we don't want a HTML-entities-encoded version here */
+ NewTemplater::Render("email/layout.html", $locale->strings, array(
+ "contents" => NewTemplater::Render("email/signup.html", $locale->strings, array(
+ "confirmation-url" => "http://boxonabudget.com/account/confirm/{$sUser->sEmailAddress}/{$sUser->sActivationKey}/",
+ "name" => $sUser->sUsername))
+ ))
+ );
+
+ $sPageContents = NewTemplater::Render("signup/success", $locale->strings, array());
+ $sPageTitle = "Thanks for signing up!";
+ return;
+ }
+}
+
+$sPageContents = NewTemplater::Render("signup/form", $locale->strings, array());
+$sPageTitle = "Sign up";
diff --git a/public_html/modules/blog/home.php b/public_html/modules/blog/home.php
new file mode 100644
index 0000000..6550bb9
--- /dev/null
+++ b/public_html/modules/blog/home.php
@@ -0,0 +1,17 @@
+strings, array());
diff --git a/public_html/modules/forums/create.php b/public_html/modules/forums/create.php
new file mode 100644
index 0000000..6211853
--- /dev/null
+++ b/public_html/modules/forums/create.php
@@ -0,0 +1,97 @@
+uTopic = $_POST['topic'];
+ $sForumThread->uSlug = $sForumThread->GenerateSlug();
+ $sForumThread->uCategoryId = $_POST['category'];
+ $sForumThread->uCreatorId = $sCurrentUser->sId;
+ $sForumThread->uPostCount = 0;
+ $sForumThread->uCreationDate = time();
+ $sForumThread->uLastReplyDate = time();
+ $sForumThread->uVisible = true;
+ $sForumThread->InsertIntoDatabase();
+
+ $sForumPost = new ForumPost(0);
+ $sForumPost->uThreadId = $sForumThread->sId;
+ $sForumPost->uBody = $_POST['body'];
+ $sForumPost->uAuthorId = $sCurrentUser->sId;
+ $sForumPost->uRevision = 1;
+ $sForumPost->uVisible = true;
+ $sForumPost->uLatestRevision = true;
+ $sForumPost->uPostedDate = time();
+ $sForumPost->uLastEditedDate = time();
+ $sForumPost->uEditExpiry = time() + (24 * 60 * 60);
+ $sForumPost->InsertIntoDatabase();
+
+ $sForumThread->uPostCount = 1;
+ $sForumThread->InsertIntoDatabase();
+
+ redirect("/forums/discussion/{$sForumThread->sId}/{$sForumThread->sSlug}");
+ }
+}
+
+$sCategories = array();
+
+try
+{
+ $result = ForumCategory::CreateFromQuery("SELECT * FROM forum_categories WHERE `Visible` = 1");
+}
+catch (NotFoundException $e)
+{
+ $result = array();
+}
+
+foreach($result as $sCategory)
+{
+ $sCategories[] = array(
+ "id" => $sCategory->sId,
+ "name" => $sCategory->sName
+ );
+}
+
+$sPageTitle = "Create new thread";
+$sPageContents = NewTemplater::Render("forum/create", $locale->strings, array(
+ "categories" => $sCategories
+));
diff --git a/public_html/modules/forums/home.php b/public_html/modules/forums/home.php
new file mode 100644
index 0000000..de61a91
--- /dev/null
+++ b/public_html/modules/forums/home.php
@@ -0,0 +1,86 @@
+uParameters[1]) ? 1 : (int) $router->uParameters[1];
+$current_page = ($current_page < 1) ? 1 : $current_page;
+
+$per_page = 10;
+$start = ($current_page - 1) * $per_page;
+
+$result = $database->CachedQuery("SELECT COUNT(*) FROM forum_threads WHERE `Visible` = 1");
+$total_threads = $result->data[0]["COUNT(*)"];
+$total_pages = ceil($total_threads / $per_page);
+
+$sThreads = array();
+
+try
+{
+ $result = ForumThread::CreateFromQuery("SELECT * FROM forum_threads WHERE `Visible` = 1 ORDER BY `Pinned` DESC, `LastReplyDate` DESC LIMIT {$start},{$per_page}");
+}
+catch (NotFoundException $e)
+{
+ $result = array();
+}
+
+foreach($result as $sThread)
+{
+ try
+ {
+ $sLastReply = $sThread->GetLastReply();
+ $sLatest = $sLastReply->sAuthor->sUsername;
+ }
+ catch (NotFoundException $e)
+ {
+ $sLatest = "";
+ }
+
+ $sThreads[] = array(
+ "title" => $sThread->sTopic,
+ "replies" => $sThread->sPostCount - 1,
+ "latest" => $sLatest,
+ "gravatar" => "https://secure.gravatar.com/avatar/" . md5(strtolower(trim($sThread->sCreator->sEmailAddress))) . ".jpg?d=retro&s=40",
+ "id" => $sThread->sId,
+ "slug" => $sThread->sSlug,
+ "pinned" => $sThread->sIsPinned,
+ "locked" => $sThread->sIsLocked
+ );
+}
+
+$sPages = array();
+
+foreach(generate_pagination(1, $total_pages, $current_page, 2, 3, 3) as $page)
+{
+ if($page === null)
+ {
+ $sPages[] = array('value' => false);
+ }
+ else
+ {
+ $sPages[] = array(
+ 'value' => $page,
+ 'current' => ($page == $current_page)
+ );
+ }
+}
+
+$sPageTitle = "Overview";
+$sPageContents = NewTemplater::Render("forum/home", $locale->strings, array(
+ "threads" => $sThreads,
+ "pagination-first" => ($current_page == 1),
+ "pagination-last" => ($current_page == $total_pages),
+ "previous-page" => ($current_page - 1),
+ "next-page" => ($current_page + 1),
+ "pages" => $sPages
+));
diff --git a/public_html/modules/forums/permalink.php b/public_html/modules/forums/permalink.php
new file mode 100644
index 0000000..9d477d5
--- /dev/null
+++ b/public_html/modules/forums/permalink.php
@@ -0,0 +1,28 @@
+uParameters[1]);
+}
+catch (NotFoundException $e)
+{
+ throw new RouterException("Post not found.");
+}
+
+$sPage = $sForumPost->GetPage();
+
+redirect("/forums/discussion/{$sForumPost->sThread->sId}/{$sForumPost->sThread->sSlug}/p{$sPage}#post_{$sForumPost->sId}");
+
diff --git a/public_html/modules/forums/reply.php b/public_html/modules/forums/reply.php
new file mode 100644
index 0000000..b4634e3
--- /dev/null
+++ b/public_html/modules/forums/reply.php
@@ -0,0 +1,52 @@
+uParameters[1]);
+}
+catch (NotFoundException $e)
+{
+ throw new RouterException("No such thread.");
+}
+
+if(empty($_POST['body']) || trim($_POST['body']) == "")
+{
+ flash_error("You can't post an empty reply.");
+ redirect("/forums/discussion/{$sForumThread->sId}/{$sForumThread->sSlug}");
+}
+
+if($sForumThread->sIsLocked === true)
+{
+ flash_error("You can't post replies to a locked discussion.");
+ redirect("/forums/discussion/{$sForumThread->sId}/{$sForumThread->sSlug}");
+}
+
+$sForumPost = new ForumPost(0);
+$sForumPost->uThreadId = $sForumThread->sId;
+$sForumPost->uBody = $_POST['body'];
+$sForumPost->uAuthorId = $sCurrentUser->sId;
+$sForumPost->uRevision = 1;
+$sForumPost->uVisible = true;
+$sForumPost->uLatestRevision = true;
+$sForumPost->uPostedDate = time();
+$sForumPost->uLastEditedDate = time();
+$sForumPost->uEditExpiry = time() + (24 * 60 * 60);
+$sForumPost->InsertIntoDatabase();
+
+$sForumThread->RecalculatePosts();
+$sForumThread->InsertIntoDatabase();
+
+redirect($sForumPost->GetPermalink());
diff --git a/public_html/modules/forums/thread.php b/public_html/modules/forums/thread.php
new file mode 100644
index 0000000..4bed0cd
--- /dev/null
+++ b/public_html/modules/forums/thread.php
@@ -0,0 +1,88 @@
+uParameters[3]) ? 1 : $router->uParameters[3];
+
+try
+{
+ $sForumThread = new ForumThread($router->uParameters[1]);
+}
+catch (NotFoundException $e)
+{
+ throw new RouterException("No such thread.");
+}
+
+
+$per_page = 30;
+$start = ($sPageNumber - 1) * $per_page;
+
+$total_posts = $sForumThread->GetPostCount();
+$total_pages = ceil($total_posts / $per_page);
+
+try
+{
+ $result = $sForumThread->GetPosts($start, $per_page);
+}
+catch (NotFoundException $e)
+{
+ throw new RouterException("Specified page does not exist.");
+}
+
+$sForumPosts = array();
+
+foreach($result as $sForumPost)
+{
+ $sForumPosts[] = array(
+ "id" => $sForumPost->sId,
+ "author" => $sForumPost->sAuthor->sUsername,
+ "author-status" => $sForumPost->sAuthor->sIsBanned ? "Banned" : "Member",
+ "body" => filter_html(Markdown($sForumPost->uBody)),
+ "date" => time_ago($sForumPost->sPostedDate, $locale),
+ "date-full" => local_from_unix($sForumPost->sPostedDate, $locale->datetime_long),
+ "self" => ($sForumPost->sAuthorId == $sCurrentUser->sId),
+ "gravatar" => "https://secure.gravatar.com/avatar/" . md5(strtolower(trim($sForumPost->sAuthor->sEmailAddress))) . ".jpg?d=retro&s=40",
+ "signature" => filter_html(Markdown($sForumPost->sAuthor->uSignature)),
+ "permalink" => $sForumPost->GetPermalink()
+ );
+}
+
+foreach(generate_pagination(1, $total_pages, $sPageNumber, 2, 3, 3) as $page)
+{
+ if($page === null)
+ {
+ $sPages[] = array('value' => false);
+ }
+ else
+ {
+ $sPages[] = array(
+ 'value' => $page,
+ 'current' => ($page == $sPageNumber)
+ );
+ }
+}
+
+$sPageTitle = $sForumThread->sTopic;
+$sPageContents = NewTemplater::Render("forum/thread", $locale->strings, array(
+ "id" => $sForumThread->sId,
+ "slug" => $sForumThread->sSlug,
+ "title" => $sForumThread->sTopic,
+ "posts" => $sForumPosts,
+ "pagination-first" => ($sPageNumber == 1),
+ "pagination-last" => ($sPageNumber == $total_pages),
+ "previous-page" => ($sPageNumber - 1),
+ "next-page" => ($sPageNumber + 1),
+ "pages" => $sPages,
+ "can-post" => ($sForumThread->sIsLocked == false)
+));
diff --git a/public_html/modules/home.php b/public_html/modules/home.php
new file mode 100644
index 0000000..ecea51c
--- /dev/null
+++ b/public_html/modules/home.php
@@ -0,0 +1,16 @@
+allow_slash = true;
+$router->ignore_query = true;
+
+$router->routes = array(
+ 0 => array(
+ "^/$" => array(
+ "target" => "modules/home.php",
+ "_section" => "Home"
+ ),
+ "^/blog$" => array(
+ "target" => "modules/blog/home.php",
+ "_section" => "Blog"
+ ),
+ "^/login$" => array(
+ "target" => "modules/account/login.php",
+ "_section" => "Account"
+ ),
+ "^/logout/([a-zA-Z0-9]+)$" => array(
+ "target" => "modules/account/logout.php",
+ "_section" => "Account"
+ ),
+ "^/account/confirm/(.+)/([a-zA-Z0-9]+)$" => array(
+ "target" => "modules/account/confirm.php",
+ "_section" => "Account"
+ ),
+ "^/sign-up$" => array(
+ "target" => "modules/account/signup.php",
+ "_section" => "Account"
+ ),
+ "^/forums$" => array(
+ "target" => "modules/forums/home.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/p([0-9]+)$" => array(
+ "target" => "modules/forums/home.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/post/([0-9]+)/[a-z0-9-]+$" => array(
+ "methods" => "get",
+ "target" => "modules/forums/permalink.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/discussion/([0-9]+)/[a-z0-9-]+(/p([0-9]))?$" => array(
+ "methods" => "get",
+ "target" => "modules/forums/thread.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/discussion/([0-9]+)/[a-z0-9-]+/reply$" => array(
+ "methods" => "post",
+ "target" => "modules/forums/reply.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/create(/([0-9]+))?$" => array(
+ "target" => "modules/forums/create.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/inbox$" => array(
+ "target" => "modules/forums/pm/home.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/inbox/([0-9]+)$" => array(
+ "methods" => "get",
+ "target" => "modules/forums/pm/read.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/inbox/([0-9]+)/reply$" => array(
+ "methods" => "post",
+ "target" => "modules/forums/pm/reply.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ ),
+ "^/forums/notifications$" => array(
+ "target" => "modules/forums/notifications.php",
+ "authenticator" => "authenticators/user.php",
+ "auth_error" => "modules/account/login.php",
+ "_section" => "Forums"
+ )
+ )
+);
+
+$router->RouteRequest();
+
+echo(NewTemplater::Render("layout", $locale->strings, array(
+ "title" => $sPageTitle,
+ "section" => $router->uVariables["section"],
+ "contents" => $sPageContents,
+ "logout-key" => "test"
+)));
+
diff --git a/public_html/static/css/style.css b/public_html/static/css/style.css
new file mode 100644
index 0000000..7eea492
--- /dev/null
+++ b/public_html/static/css/style.css
@@ -0,0 +1,560 @@
+body
+{
+ background-color: #E3FFE3;
+ font-family: sans-serif;
+ margin: 0px;
+}
+
+.clear
+{
+ clear: both;
+}
+
+.wrapper
+{
+ width: 900px;
+ margin: 0px auto;
+ border-radius: 0px 0px 4px 4px;
+ box-shadow: 0px 0px 8px 0px #618f5d;
+ -webkit-box-shadow: 0px 0px 8px 0px #618f5d;
+ -moz-box-shadow: 0px 0px 8px 0px #618f5d;
+ -o-box-shadow: 0px 0px 8px 0px #618f5d;
+ -ms-box-shadow: 0px 0px 8px 0px #618f5d;
+}
+
+.header
+{
+ background-color: #4A8D4A;
+ padding: 6px 11px;
+}
+
+.main
+{
+ background-color: #FFFFFF;
+ padding: 11px 16px;
+}
+
+.footer
+{
+ background-color: #4D4D4D;
+ color: white;
+ font-weight: bold;
+ font-size: 13px;
+ padding: 9px 13px;
+ border-radius: 0px 0px 4px 4px;
+}
+
+.footer a
+{
+ color: #E2F3E0;
+ text-decoration: underline;
+}
+
+.footer a:hover
+{
+ color: #D0ECCD;
+}
+
+.logo
+{
+ float: left;
+ color: white;
+ font-size: 24px;
+ font-weight: bold;
+ margin-right: 18px;
+ margin-top: 6px;
+}
+
+.menu div
+{
+ float: left;
+ margin-left: 16px;
+ margin-top: 1px;
+ padding: 3px 4px;
+ border-radius: 6px;
+}
+
+.menu div.active
+{
+ background-color: #295829;
+ border: 1px inset #368A36;
+}
+
+.menu a
+{
+ display: block;
+ float: left;
+ padding: 7px 8px;
+ text-decoration: none;
+ color: white;
+ font-size: 15px;
+ border-radius: 4px;
+}
+
+.menu a:hover
+{
+ color: white;
+ background-color: #336D27;
+
+}
+
+.menu a.section
+{
+ font-weight: bold;
+}
+
+a
+{
+ color: #219516;
+ text-decoration: none;
+}
+
+a:hover
+{
+ color: #154311;
+}
+
+h1, h2, h3
+{
+ margin: 3px 0px 11px 0px;
+ color: #1A3717;
+}
+
+form .field
+{
+ margin-bottom: 7px;
+}
+
+label, input, textarea
+{
+ display: block;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+}
+
+label, input, select
+{
+ float: left;
+}
+
+label
+{
+ width: 18%;
+ font-size: 19px;
+ color: #397739;
+ font-weight: bold;
+ margin-top: 6px;
+}
+
+input, textarea, select
+{
+ border: 1px solid #397739;
+ background-color: white;
+ border-radius: 1px;
+}
+
+input, select
+{
+ width: 82%;
+ font-size: 19px;
+ padding: 2px 4px;
+}
+
+textarea
+{
+ width: 100%;
+ height: 250px;
+ padding: 9px;
+ font-size: 17px;
+ font-family: sans-serif;
+}
+
+button, a.button
+{
+ font-size: 17px;
+ font-weight: bold;
+ background: #f5fff2; /* Old browsers */
+ background: -moz-linear-gradient(top, #f5fff2 34%, #e9f7d7 74%, #ddefc9 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(34%,#f5fff2), color-stop(74%,#e9f7d7), color-stop(100%,#ddefc9)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #f5fff2 34%,#e9f7d7 74%,#ddefc9 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #f5fff2 34%,#e9f7d7 74%,#ddefc9 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #f5fff2 34%,#e9f7d7 74%,#ddefc9 100%); /* IE10+ */
+ background: linear-gradient(to bottom, #f5fff2 34%,#e9f7d7 74%,#ddefc9 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5fff2', endColorstr='#ddefc9',GradientType=0 ); /* IE6-9 */
+ color: #2E4F2B;
+ border: 1px solid silver;
+ border-radius: 4px;
+ padding: 5px 8px;
+ box-shadow: 0px 0px 4px 0px #c0dbba;
+ -webkit-box-shadow: 0px 0px 4px 0px #c0dbba;
+ -moz-box-shadow: 0px 0px 4px 0px #c0dbba;
+ -o-box-shadow: 0px 0px 4px 0px #c0dbba;
+ -ms-box-shadow: 0px 0px 4px 0px #c0dbba;
+ text-shadow: 1px 1px 0px #bbe6a6;
+ -webkit-text-shadow: 1px 1px 0px #bbe6a6;
+ -moz-text-shadow: 1px 1px 0px #bbe6a6;
+ -o-text-shadow: 1px 1px 0px #bbe6a6;
+ -ms-text-shadow: 1px 1px 0px #bbe6a6;
+}
+
+button.large, a.button.large
+{
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ width: 100%;
+ height: 51px;
+ text-align: center;
+ padding-top: 12px;
+ font-size: 19px;
+}
+
+button:active, a.button:active
+{
+ background: #ddefc9; /* Old browsers */
+ background: -moz-linear-gradient(top, #ddefc9 0%, #e9f7d7 26%, #f5fff2 66%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ddefc9), color-stop(26%,#e9f7d7), color-stop(66%,#f5fff2)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #ddefc9 0%,#e9f7d7 26%,#f5fff2 66%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #ddefc9 0%,#e9f7d7 26%,#f5fff2 66%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, #ddefc9 0%,#e9f7d7 26%,#f5fff2 66%); /* IE10+ */
+ background: linear-gradient(to bottom, #ddefc9 0%,#e9f7d7 26%,#f5fff2 66%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ddefc9', endColorstr='#f5fff2',GradientType=0 ); /* IE6-9 */
+}
+
+button.post
+{
+ float: right;
+}
+
+.subtext
+{
+ font-size: 14px;
+ color: #1F751F;
+ font-weight: bold;
+}
+
+.sidebar
+{
+ float: right;
+ width: 230px;
+}
+
+#button_newthread, button.submit
+{
+ float: right;
+}
+
+.errors, .notice
+{
+ padding: 10px 12px;
+ margin: 0px 0px 12px 0px;
+ font-size: 14px;
+}
+
+.errors
+{
+ background-color: #FFF9EA;
+ border: 1px solid #FFC024;
+}
+
+.errors .intro
+{
+ font-weight: bold;
+}
+
+.errors ul
+{
+ margin: 5px 0px 0px 0px;
+ padding-left: 22px;
+}
+
+.notice
+{
+ background-color: #F1FAF1;
+ border: 1px solid #3AB223;
+}
+
+form.narrow
+{
+ width: 550px;
+ margin: 0px auto;
+}
+
+form.narrow label
+{
+ width: 40%;
+}
+
+form.narrow input, form.narrow textarea, form.narrow select
+{
+ width: 60%;
+}
+
+.contents
+{
+ padding-right: 250px;
+}
+
+.thread
+{
+ border-bottom: 1px solid #BBC8BB;
+ padding: 7px 8px;
+}
+
+.thread .title
+{
+ margin-top: 4px;
+ font-size: 18px;
+ font-weight: bold;
+}
+
+.thread .title a
+{
+ color: #387338;
+}
+
+.thread .metadata
+{
+ color: gray;
+ font-size: 13px;
+ margin-top: 2px;
+}
+
+.thread .metadata .author, .thread .metadata .replycount, .thread .metadata .pinned, .thread .metadata .locked
+{
+ float: left;
+ margin-right: 14px;
+}
+
+.thread .metadata .pinned, .thread .metadata .locked
+{
+ font-size: 11px;
+ border-radius: 4px;
+ color: white;
+ font-weight: bold;
+ padding: 2px 4px;
+ margin-top: -1px;
+}
+
+.thread .metadata .pinned
+{
+ background-color: #219621;
+}
+
+.thread .metadata .locked
+{
+ background-color: #7C7C7C;
+}
+
+.thread .avatar, .post .avatar
+{
+ display: block;
+ float: left;
+ padding: 1px;
+ border: 1px solid silver;
+ margin: 2px 11px 2px 0px;
+}
+
+a.user
+{
+ color: black;
+}
+
+.post
+{
+ border-top: 1px solid #B0B0B0;
+}
+
+.post .main
+{
+ padding: 9px 5px 2px 5px;
+}
+
+.post .metadata
+{
+ float: left;
+ color: gray;
+ font-size: 13px;
+ width: 500px;
+}
+
+.post .metadata .primary
+{
+ margin-top: 4px;
+}
+
+.post .metadata .author, .post .metadata .date, .post .metadata .thanks, .post .metadata .flag, .post .metadata .status
+{
+ margin-right: 12px;
+}
+
+.post .metadata .date
+{
+ color: gray;
+}
+
+.post .metadata .author
+{
+ color: black;
+ font-size: 17px;
+ font-weight: bold;
+}
+
+.post .metadata .status
+{
+ margin-top: 1px;
+}
+
+.post .body
+{
+ font-size: 15px;
+ margin-top: 8px;
+ padding: 1px 3px;
+}
+
+.post .body h1, .post .body h2, .post .body h3, .post .body h4, .post .body h5, .post .body h6
+{
+ margin: 3px 0px 11px 0px;
+ color: #1A3717;
+}
+
+.post .body h1 { font-size: 32px; }
+.post .body h2 { font-size: 28px; }
+.post .body h3 { font-size: 24px; }
+.post .body h4 { font-size: 20px; }
+.post .body h5 { font-size: 16px; }
+.post .body h6 { font-size: 14px; }
+
+.post .body blockquote
+{
+ padding: 7px 0px 7px 9px;
+ margin: 9px 0px 9px 6px;
+ border-left: 3px solid #80B380;
+}
+
+.post .body blockquote p
+{
+ margin: 0px;
+}
+
+.post .body p
+{
+ margin-top: 0px;
+}
+
+.post .signature
+{
+ border-top: 1px solid #E7E7E7;
+ font-size: 11px;
+ padding: 0px 5px;
+ max-height: 34px;
+ overflow: auto;
+}
+
+.post .signature p
+{
+ margin: 4px 0px;
+ color: gray;
+}
+
+.pagination
+{
+ margin-top: 6px;
+ text-align: right;
+ font-size: 17px;
+ font-weight: bold;
+}
+
+.pagination a
+{
+ margin-right: 2px;
+}
+
+.pagination a.current
+{
+ color: #313131;
+}
+
+.pagination.line
+{
+ border-top: 1px solid silver;
+ padding-top: 6px;
+ margin-top: 0px;
+}
+
+.reply
+{
+ background-color: #F4FCF4;
+ border: 1px solid #B1D2B1;
+ /*border-top: 1px solid gray;*/
+ margin: 16px 0px 0px 0px;
+ padding: 8px 12px 4px 12px;
+}
+
+.reply textarea
+{
+ border: 1px solid #BFE4BF;
+ height: 160px;
+}
+
+button.preview
+{
+ margin-top: 6px;
+ margin-right: 8px;
+ font-size: 15px;
+ text-shadow: none;
+}
+
+.entry
+{
+ text-align: justify;
+ border-bottom: 1px solid gray;
+ padding: 8px 12px 20px 12px;
+}
+
+.entry p
+{
+ margin: 8px 0px;
+}
+
+.entry h1
+{
+ font-size: 28px;
+ font-weight: bold;
+ margin: 12px 0px 4px 0px;
+ text-align: left;
+}
+
+.entry img
+{
+ display: block;
+ float: right;
+ width: 210px;
+ padding: 1px;
+ border: 1px solid silver;
+ margin: 8px 0px 8px 18px;
+}
+
+.entry ul
+{
+ text-align: left;
+}
+
+.entry a.readmore
+{
+ display: block;
+ margin-top: 16px;
+ font-weight: bold;
+}
+
+.entry .metadata
+{
+ margin: 8px 0px 8px 0px;
+ color: #4A4A4A;
+ font-size: 15px;
+ font-weight: bold;
+}
+
+.entry .metadata .author
+{
+ margin-right: 18px;
+}
diff --git a/public_html/static/images/crowncloud.jpg b/public_html/static/images/crowncloud.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..396c6066bfbb36fdd32376d134f70e5adab872c3
GIT binary patch
literal 33783
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
U4``YF_I2K$vj*3wLEpyyA2wNhi2wiq
literal 0
HcmV?d00001
diff --git a/public_html/static/images/infinityhosts.jpg b/public_html/static/images/infinityhosts.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..22b2a79fdd149cc894982679623ca654989dc2bf
GIT binary patch
literal 26563
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Ò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