Swift-4.2.1/ 40755 0 0 0 12000050367 7635 5ustar 0 0 Swift-4.2.1/lib/ 40755 0 0 0 12000050366 10402 5ustar 0 0 Swift-4.2.1/lib/classes/ 40755 0 0 0 12000050366 12037 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/ 40755 0 0 0 12000050366 13133 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/ByteStream/ 40755 0 0 0 12000050366 15212 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/CharacterReader/ 40755 0 0 0 12000050366 16152 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/CharacterReaderFactory/ 40755 0 0 0 12000050366 17502 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/CharacterStream/ 40755 0 0 0 12000050366 16203 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Encoder/ 40755 0 0 0 12000050366 14512 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Events/ 40755 0 0 0 12000050366 14377 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/KeyCache/ 40755 0 0 0 12000050366 14607 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Mailer/ 40755 0 0 0 12000050366 14344 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Mime/ 40755 0 0 0 12000050366 14022 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Mime/ContentEncoder/ 40755 0 0 0 12000050366 16734 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Mime/HeaderEncoder/ 40755 0 0 0 12000050366 16512 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Mime/Headers/ 40755 0 0 0 12000050366 15375 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Plugins/ 40755 0 0 0 12000050366 14554 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Plugins/Decorator/ 40755 0 0 0 12000050366 16476 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Plugins/Loggers/ 40755 0 0 0 12000050366 16156 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Plugins/Pop/ 40755 0 0 0 12000050366 15312 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Plugins/Reporters/ 40755 0 0 0 12000050366 16541 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/StreamFilters/ 40755 0 0 0 12000050366 15717 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Transport/ 40755 0 0 0 12000050366 15127 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/ 40755 0 0 0 12000050366 16217 5ustar 0 0 Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/Auth/ 40755 0 0 0 12000050366 17120 5ustar 0 0 Swift-4.2.1/lib/dependency_maps/ 40755 0 0 0 12000050366 13540 5ustar 0 0 Swift-4.2.1/test-suite/ 40755 0 0 0 12000050366 11742 5ustar 0 0 Swift-4.2.1/test-suite/lib/ 40755 0 0 0 12000050366 12510 5ustar 0 0 Swift-4.2.1/test-suite/lib/Sweety/ 40755 0 0 0 12000050366 13770 5ustar 0 0 Swift-4.2.1/test-suite/lib/Sweety/Reporter/ 40755 0 0 0 12000050366 15572 5ustar 0 0 Swift-4.2.1/test-suite/lib/Sweety/Runner/ 40755 0 0 0 12000050366 15241 5ustar 0 0 Swift-4.2.1/test-suite/lib/Sweety/TestLocator/ 40755 0 0 0 12000050366 16233 5ustar 0 0 Swift-4.2.1/test-suite/lib/simpletest/ 40755 0 0 0 12000050367 14702 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/ 40755 0 0 0 12000050366 14164 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/classes/ 40755 0 0 0 12000050366 15621 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/ 40755 0 0 0 12000050366 16363 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Actions/ 40755 0 0 0 12000050366 17763 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/ 40755 0 0 0 12000050366 21031 5ustar 0 0 Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/ 40755 0 0 0 12000050366 20131 5ustar 0 0 Swift-4.2.1/test-suite/templates/ 40755 0 0 0 12000050366 13740 5ustar 0 0 Swift-4.2.1/test-suite/templates/sweety/ 40755 0 0 0 12000050366 15260 5ustar 0 0 Swift-4.2.1/test-suite/templates/sweety/css/ 40755 0 0 0 12000050366 16050 5ustar 0 0 Swift-4.2.1/test-suite/templates/sweety/images/ 40755 0 0 0 12000050366 16525 5ustar 0 0 Swift-4.2.1/test-suite/templates/sweety/js/ 40755 0 0 0 12000050366 15674 5ustar 0 0 Swift-4.2.1/tests/ 40755 0 0 0 12000050367 10777 5ustar 0 0 Swift-4.2.1/tests/_samples/ 40755 0 0 0 12000050367 12602 5ustar 0 0 Swift-4.2.1/tests/_samples/charsets/ 40755 0 0 0 12000050367 14416 5ustar 0 0 Swift-4.2.1/tests/_samples/charsets/iso-2022-jp/ 40755 0 0 0 12000050367 16202 5ustar 0 0 Swift-4.2.1/tests/_samples/charsets/iso-8859-1/ 40755 0 0 0 12000050367 15761 5ustar 0 0 Swift-4.2.1/tests/_samples/charsets/utf-8/ 40755 0 0 0 12000050367 15361 5ustar 0 0 Swift-4.2.1/tests/_samples/files/ 40755 0 0 0 12000050367 13704 5ustar 0 0 Swift-4.2.1/tests/acceptance/ 40755 0 0 0 12000050367 13065 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/ 40755 0 0 0 12000050367 14161 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/ByteStream/ 40755 0 0 0 12000050367 16240 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/CharacterReaderFactory/ 40755 0 0 0 12000050367 20530 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Encoder/ 40755 0 0 0 12000050367 15540 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/KeyCache/ 40755 0 0 0 12000050367 15635 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Mime/ 40755 0 0 0 12000050367 15050 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Mime/ContentEncoder/ 40755 0 0 0 12000050367 17762 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Mime/HeaderEncoder/ 40755 0 0 0 12000050367 17540 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Transport/ 40755 0 0 0 12000050367 16155 5ustar 0 0 Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/ 40755 0 0 0 12000050367 20542 5ustar 0 0 Swift-4.2.1/tests/bug/ 40755 0 0 0 12000050367 11554 5ustar 0 0 Swift-4.2.1/tests/bug/Swift/ 40755 0 0 0 12000050367 12650 5ustar 0 0 Swift-4.2.1/tests/helpers/ 40755 0 0 0 12000050367 12441 5ustar 0 0 Swift-4.2.1/tests/helpers/Swift/ 40755 0 0 0 12000050367 13535 5ustar 0 0 Swift-4.2.1/tests/helpers/Swift/Tests/ 40755 0 0 0 12000050367 14637 5ustar 0 0 Swift-4.2.1/tests/smoke/ 40755 0 0 0 12000050367 12115 5ustar 0 0 Swift-4.2.1/tests/smoke/Swift/ 40755 0 0 0 12000050367 13211 5ustar 0 0 Swift-4.2.1/tests/smoke/Swift/Smoke/ 40755 0 0 0 12000050367 14267 5ustar 0 0 Swift-4.2.1/tests/unit/ 40755 0 0 0 12000050367 11756 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/ 40755 0 0 0 12000050367 13052 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/ByteStream/ 40755 0 0 0 12000050367 15131 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/CharacterReader/ 40755 0 0 0 12000050367 16071 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/CharacterStream/ 40755 0 0 0 12000050367 16122 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Encoder/ 40755 0 0 0 12000050367 14431 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Events/ 40755 0 0 0 12000050367 14316 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/KeyCache/ 40755 0 0 0 12000050367 14526 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Mailer/ 40755 0 0 0 12000050367 14263 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Mime/ 40755 0 0 0 12000050367 13741 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Mime/ContentEncoder/ 40755 0 0 0 12000050367 16653 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Mime/HeaderEncoder/ 40755 0 0 0 12000050367 16431 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Mime/Headers/ 40755 0 0 0 12000050367 15314 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Plugins/ 40755 0 0 0 12000050367 14473 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Plugins/Loggers/ 40755 0 0 0 12000050367 16075 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Plugins/Reporters/ 40755 0 0 0 12000050367 16460 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/StreamFilters/ 40755 0 0 0 12000050367 15636 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Transport/ 40755 0 0 0 12000050367 15046 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/ 40755 0 0 0 12000050367 16136 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/Auth/ 40755 0 0 0 12000050367 17037 5ustar 0 0 Swift-4.2.1/tests/unit/Swift/Transport/EsmtpTransport/ 40755 0 0 0 12000050367 20053 5ustar 0 0 Swift-4.2.1/CHANGES100644 0 0 5657 12000050367 10742 0ustar 0 0 Changelog since Version 4.x.x ============================= 4.2.1 (2012-07-13) ------------------ * changed the coding standards to PSR-1/2 * fixed issue with autoloading * added NativeQpContentEncoder to enhance performance (for PHP 5.3+) 4.2.0 (2012-06-29) ------------------ * added documentation about how to use the Japanese support introduced in 4.1.8 * added a way to override the default configuration in a lazy way * changed the PEAR init script to lazy-load the initialization * fixed a bug when calling Swift_Preferences before anything else (regression introduced in 4.1.8) 4.1.8 (2012-06-17) ------------------ * added Japanese iso-2022-jp support * changed the init script to lazy-load the initialization * fixed docblocks (@id) which caused some problems with libraries parsing the dobclocks * fixed Swift_Mime_Headers_IdentificationHeader::setId() when passed an array of ids * fixed encoding of email addresses in headers * added replacements setter to the Decorator plugin 4.1.7 (2012-04-26) ------------------ * fixed QpEncoder safeMapShareId property 4.1.6 (2012-03-23) ------------------ * reduced the size of serialized Messages 4.1.5 (2012-01-04) ------------------ * enforced Swift_Spool::queueMessage() to return a Boolean * made an optimization to the memory spool: start the transport only when required * prevented stream_socket_client() from generating an error and throw a Swift_TransportException instead * fixed a PHP warning when calling to mail() when safe_mode is off * many doc tweaks 4.1.4 (2011-12-16) ------------------ * added a memory spool (Swift_MemorySpool) * fixed too many opened files when sending emails with attachments 4.1.3 (2011-10-27) ------------------ * added STARTTLS support * added missing @return tags on fluent methods * added a MessageLogger plugin that logs all sent messages * added composer.json 4.1.2 (2011-09-13) ------------------ * fixed wrong detection of magic_quotes_runtime * fixed fatal errors when no To or Subject header has been set * fixed charset on parameter header continuations * added documentation about how to install Swiftmailer from the PEAR channel * fixed various typos and markup problem in the documentation * fixed warning when cache directory does not exist * fixed "slashes are escaped" bug * changed require_once() to require() in autoload 4.1.1 (2011-07-04) ------------------ * added missing file in PEAR package 4.1.0 (2011-06-30) ------------------ * documentation has been converted to ReST 4.1.0 RC1 (2011-06-17) ---------------------- New features: * changed the Decorator Plugin to allow replacements in all headers * added Swift_Mime_Grammar and Swift_Validate to validate an email address * modified the autoloader to lazy-initialize Swiftmailer * removed Swift_Mailer::batchSend() * added NullTransport * added new plugins: RedirectingPlugin and ImpersonatePlugin * added a way to send messages asynchronously (Spool) Swift-4.2.1/LICENSE100644 0 0 16727 12000050367 10774 0ustar 0 0 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. Swift-4.2.1/README100644 0 0 1101 12000050367 10603 0ustar 0 0 Swift Mailer ------------ Swift Mailer is a component based mailing solution for PHP 5. It is released under the LGPL license. Homepage: http://swiftmailer.org Documentation: http://swiftmailer.org/docs Mailing List: http://groups.google.com/group/swiftmailer Bugs: https://github.com/swiftmailer/swiftmailer/issues Repository: https://github.com/swiftmailer/swiftmailer Swift Mailer is highly object-oriented by design and lends itself to use in complex web application with a great deal of flexibility. For full details on usage, see the documentation. Swift-4.2.1/VERSION100644 0 0 14 12000050367 10735 0ustar 0 0 Swift-4.2.1 Swift-4.2.1/lib/classes/Swift.php100644 0 0 4054 12000050366 13744 0ustar 0 0 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 ); } } Swift-4.2.1/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php100644 0 0 10052 12000050366 23767 0ustar 0 0 _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 * @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 = ''; } } Swift-4.2.1/lib/classes/Swift/ByteStream/ArrayByteStream.php100644 0 0 10255 12000050366 21121 0ustar 0 0 _array = $stack; $this->_arraySize = count($stack); } elseif (is_string($stack)) { $this->write($stack); } else { $this->_array = array(); } } /** * Reads $length bytes from the stream into a string and moves the pointer * through the stream by $length. If less bytes exist than are requested the * remaining bytes are given instead. If no bytes are remaining at all, boolean * false is returned. * @param int $length * @return string */ public function read($length) { if ($this->_offset == $this->_arraySize) { return false; } // Don't use array slice $end = $length + $this->_offset; $end = $this->_arraySize<$end ?$this->_arraySize :$end; $ret = ''; for (; $this->_offset < $end; ++$this->_offset) { $ret .= $this->_array[$this->_offset]; } return $ret; } /** * Writes $bytes to the end of the stream. * @param string $bytes */ public function write($bytes) { $to_add = str_split($bytes); foreach ($to_add as $value) { $this->_array[] = $value; } $this->_arraySize = count($this->_array); foreach ($this->_mirrors as $stream) { $stream->write($bytes); } } /** * Not used. */ public function commit() { } /** * Attach $is to this stream. * The stream acts as an observer, receiving all data that is written. * All {@link write()} and {@link flushBuffers()} operations will be mirrored. * * @param Swift_InputByteStream $is */ public function bind(Swift_InputByteStream $is) { $this->_mirrors[] = $is; } /** * Remove an already bound stream. * If $is is not bound, no errors will be raised. * If the stream currently has any buffered data it will be written to $is * before unbinding occurs. * * @param Swift_InputByteStream $is */ public function unbind(Swift_InputByteStream $is) { foreach ($this->_mirrors as $k => $stream) { if ($is === $stream) { unset($this->_mirrors[$k]); } } } /** * Move the internal read pointer to $byteOffset in the stream. * @param int $byteOffset * @return 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(); } } } Swift-4.2.1/lib/classes/Swift/ByteStream/FileByteStream.php100644 0 0 14067 12000050366 20727 0ustar 0 0 _path = $path; $this->_mode = $writable ? 'w+b' : 'rb'; if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) { $this->_quotes = true; } } /** * Get the complete path to the file. * @return string */ public function getPath() { return $this->_path; } /** * Reads $length bytes from the stream into a string and moves the pointer * through the stream by $length. If less bytes exist than are requested the * remaining bytes are given instead. If no bytes are remaining at all, boolean * false is returned. * @param int $length * @return string * @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 int $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; } } Swift-4.2.1/lib/classes/Swift/CharacterReader.php100644 0 0 3227 12000050366 16764 0ustar 0 0 */ interface Swift_CharacterReader { const MAP_TYPE_INVALID = 0x01; const MAP_TYPE_FIXED_LEN = 0x02; const MAP_TYPE_POSITIONS = 0x03; /** * Returns the complete charactermap * * @param string $string * @param int $startOffset * @param array $currentMap * @param mixed $ignoredChars * @return int */ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars); /** * Returns mapType * @return int mapType */ 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 int[] $bytes * @return int */ public function validateByteSequence($bytes, $size); /** * Returns the number of bytes which should be read to start each character. * For fixed width character sets this should be the number of * octets-per-character. For multibyte character sets this will probably be 1. * @return int */ public function getInitialByteSize(); } Swift-4.2.1/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php100644 0 0 4420 12000050366 23437 0ustar 0 0 */ class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader { /** * The number of bytes in a single character. * @var int * @access private */ private $_width; /** * Creates a new GenericFixedWidthReader using $width bytes per character. * @param int $width */ public function __construct($width) { $this->_width = $width; } /** * Returns the complete charactermap * * @param string $string * @param int $startOffset * @param array $currentMap * @param mixed $ignoredChars * @return $int */ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) { $strlen = strlen($string); // % and / are CPU intensive, so, maybe find a better way $ignored = $strlen%$this->_width; $ignoredChars = substr($string, - $ignored); $currentMap = $this->_width; return ($strlen - $ignored)/$this->_width; } /** * Returns mapType * @return int mapType */ 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 * @return int */ public function validateByteSequence($bytes, $size) { $needed = $this->_width - $size; return ($needed > -1) ? $needed : -1; } /** * Returns the number of bytes which should be read to start each character. * @return int */ public function getInitialByteSize() { return $this->_width; } } Swift-4.2.1/lib/classes/Swift/CharacterReader/UsAsciiReader.php100644 0 0 3535 12000050366 21451 0ustar 0 0 "\x07F") { // Invalid char $currentMap[$i+$startOffset]=$string[$i]; } } return $strlen; } /** * Returns mapType * @return int mapType */ public function getMapType() { return self::MAP_TYPE_INVALID; } /** * Returns an integer which specifies how many more bytes to read. * A positive integer indicates the number of more bytes to fetch before invoking * this method again. * A value of zero means this is already a valid character. * A value of -1 means this cannot possibly be a valid character. * @param string $bytes * @return int */ public function validateByteSequence($bytes, $size) { $byte = reset($bytes); if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { return 0; } else { return -1; } } /** * Returns the number of bytes which should be read to start each character. * @return int */ public function getInitialByteSize() { return 1; } } Swift-4.2.1/lib/classes/Swift/CharacterReader/Utf8Reader.php100644 0 0 16153 12000050366 20757 0ustar 0 0 */ 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 charactermap * * @param string $string * @param int $startOffset * @param array $currentMap * @param mixed $ignoredChars */ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) { if (!isset($currentMap['i']) || !isset($currentMap['p'])) { $currentMap['p'] = $currentMap['i'] = array(); } $strlen=strlen($string); $charPos=count($currentMap['p']); $foundChars=0; $invalid=false; for ($i=0; $i<$strlen; ++$i) { $char=$string[$i]; $size=self::$s_length_map[$char]; if ($size==0) { /* char is invalid, we must wait for a resync */ $invalid=true; continue; } else { if ($invalid==true) { /* We mark the chars as invalid and start a new char */ $currentMap['p'][$charPos+$foundChars]=$startOffset+$i; $currentMap['i'][$charPos+$foundChars]=true; ++$foundChars; $invalid=false; } if (($i+$size) > $strlen) { $ignoredChars=substr($string, $i); break; } for ($j=1; $j<$size; ++$j) { $char=$string[$i+$j]; if ($char>"\x7F" && $char<"\xC0") { // Valid - continue parsing } else { /* char is invalid, we must wait for a resync */ $invalid=true; continue 2; } } /* Ok we got a complete char here */ $currentMap['p'][$charPos+$foundChars]=$startOffset+$i+$size; $i+=$j-1; ++$foundChars; } } return $foundChars; } /** * Returns mapType * @return int mapType */ public function getMapType() { return self::MAP_TYPE_POSITIONS; } /** * Returns an integer which specifies how many more bytes to read. * A positive integer indicates the number of more bytes to fetch before invoking * this method again. * A value of zero means this is already a valid character. * A value of -1 means this cannot possibly be a valid character. * @param string $bytes * @return int */ public function validateByteSequence($bytes, $size) { if ($size<1) { return -1; } $needed = self::$length_map[$bytes[0]] - $size; return ($needed > -1) ? $needed : -1 ; } /** * Returns the number of bytes which should be read to start each character. * @return int */ public function getInitialByteSize() { return 1; } } Swift-4.2.1/lib/classes/Swift/CharacterReaderFactory.php100644 0 0 1106 12000050366 20306 0ustar 0 0 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]; } } } } Swift-4.2.1/lib/classes/Swift/CharacterStream.php100644 0 0 4420 12000050366 17011 0ustar 0 0 setCharacterReaderFactory($factory); $this->setCharacterSet($charset); } /** * Set the character set used in this CharacterStream. * @param string $charset */ public function setCharacterSet($charset) { $this->_charset = $charset; $this->_charReader = null; } /** * Set the CharacterReaderFactory for multi charset support. * @param Swift_CharacterReaderFactory $factory */ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) { $this->_charReaderFactory = $factory; } /** * Overwrite this character stream using the byte sequence in the byte stream. * @param Swift_OutputByteStream $os output stream to read from */ public function importByteStream(Swift_OutputByteStream $os) { if (!isset($this->_charReader)) { $this->_charReader = $this->_charReaderFactory ->getReaderFor($this->_charset); } $startLength = $this->_charReader->getInitialByteSize(); while (false !== $bytes = $os->read($startLength)) { $c = array(); for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { $c[] = self::$_byteMap[$bytes[$i]]; } $size = count($c); $need = $this->_charReader ->validateByteSequence($c, $size); if ($need > 0 && false !== $bytes = $os->read($need)) { for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { $c[] = self::$_byteMap[$bytes[$i]]; } } $this->_array[] = $c; ++$this->_array_size; } } /** * Import a string a bytes into this CharacterStream, overwriting any existing * data in the stream. * @param string $string */ public function importString($string) { $this->flushContents(); $this->write($string); } /** * Read $length characters from the stream and move the internal pointer * $length further into the stream. * @param int $length * @return string */ public function read($length) { if ($this->_offset == $this->_array_size) { return false; } // Don't use array slice $arrays = array(); $end = $length + $this->_offset; for ($i = $this->_offset; $i < $end; ++$i) { if (!isset($this->_array[$i])) { break; } $arrays[] = $this->_array[$i]; } $this->_offset += $i - $this->_offset; // Limit function calls $chars = false; foreach ($arrays as $array) { $chars .= implode('', array_map('chr', $array)); } return $chars; } /** * Read $length characters from the stream and return a 1-dimensional array * containing there octet values. * @param int $length * @return int[] */ public function readBytes($length) { if ($this->_offset == $this->_array_size) { return false; } $arrays = array(); $end = $length + $this->_offset; for ($i = $this->_offset; $i < $end; ++$i) { if (!isset($this->_array[$i])) { break; } $arrays[] = $this->_array[$i]; } $this->_offset += ($i - $this->_offset); // Limit function calls return call_user_func_array('array_merge', $arrays); } /** * Write $chars to the end of the stream. * @param string $chars */ public function write($chars) { if (!isset($this->_charReader)) { $this->_charReader = $this->_charReaderFactory->getReaderFor( $this->_charset); } $startLength = $this->_charReader->getInitialByteSize(); $fp = fopen('php://memory', 'w+b'); fwrite($fp, $chars); unset($chars); fseek($fp, 0, SEEK_SET); $buffer = array(0); $buf_pos = 1; $buf_len = 1; $has_datas = true; do { $bytes = array(); // Buffer Filing if ($buf_len - $buf_pos < $startLength) { $buf = array_splice($buffer, $buf_pos); $new = $this->_reloadBuffer($fp, 100); if ($new) { $buffer = array_merge($buf, $new); $buf_len = count($buffer); $buf_pos = 0; } else { $has_datas = false; } } if ($buf_len - $buf_pos > 0) { $size = 0; for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { ++$size; $bytes[] = $buffer[$buf_pos++]; } $need = $this->_charReader->validateByteSequence( $bytes, $size); if ($need > 0) { if ($buf_len - $buf_pos < $need) { $new = $this->_reloadBuffer($fp, $need); if ($new) { $buffer = array_merge($buffer, $new); $buf_len = count($buffer); } } for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { $bytes[] = $buffer[$buf_pos++]; } } $this->_array[] = $bytes; ++$this->_array_size; } } while ($has_datas); fclose($fp); } /** * Move the internal pointer to $charOffset in the stream. * @param int $charOffset */ public function setPointer($charOffset) { if ($charOffset > $this->_array_size) { $charOffset = $this->_array_size; } elseif ($charOffset < 0) { $charOffset = 0; } $this->_offset = $charOffset; } /** * Empty the stream and reset the internal pointer. */ public function flushContents() { $this->_offset = 0; $this->_array = array(); $this->_array_size = 0; } private function _reloadBuffer($fp, $len) { if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) { $buf = array(); for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { $buf[] = self::$_byteMap[$bytes[$i]]; } return $buf; } return false; } private static function _initializeMaps() { if (!isset(self::$_charMap)) { self::$_charMap = array(); for ($byte = 0; $byte < 256; ++$byte) { self::$_charMap[$byte] = chr($byte); } self::$_byteMap = array_flip(self::$_charMap); } } } Swift-4.2.1/lib/classes/Swift/CharacterStream/NgCharacterStream.php100644 0 0 16652 12000050366 22400 0ustar 0 0 . */ /** * A CharacterStream implementation which stores characters in an internal array. * @package Swift * @subpackage CharacterStream * @author Xavier De Cock */ class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream { /** * The char reader (lazy-loaded) for the current charset. * @var Swift_CharacterReader * @access private */ private $_charReader; /** * A factory for creatiing CharacterReader instances. * @var Swift_CharacterReaderFactory * @access private */ private $_charReaderFactory; /** * The character set this stream is using. * @var string * @access private */ private $_charset; /** * The datas stored as is * * @var string */ private $_datas = ""; /** * Number of bytes in the stream * * @var int */ private $_datasSize = 0; /** * Map * * @var mixed */ private $_map; /** * Map Type * * @var int */ private $_mapType = 0; /** * Number of characters in the stream * * @var int */ private $_charCount = 0; /** * Position in the stream * * @var unknown_type */ private $_currentPos = 0; /** * The constructor * * @param Swift_CharacterReaderFactory $factory * @param unknown_type $charset */ public function __construct(Swift_CharacterReaderFactory $factory, $charset) { $this->setCharacterReaderFactory($factory); $this->setCharacterSet($charset); } /* -- Changing parameters of the stream -- */ /** * Set the character set used in this CharacterStream. * @param string $charset */ public function setCharacterSet($charset) { $this->_charset = $charset; $this->_charReader = null; $this->_mapType = 0; } /** * Set the CharacterReaderFactory for multi charset support. * @param Swift_CharacterReaderFactory $factory */ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) { $this->_charReaderFactory = $factory; } /** * @see Swift_CharacterStream::flushContents() * */ public function flushContents() { $this->_datas = null; $this->_map = null; $this->_charCount = 0; $this->_currentPos = 0; $this->_datasSize = 0; } /** * @see Swift_CharacterStream::importByteStream() * * @param Swift_OutputByteStream $os */ public function importByteStream(Swift_OutputByteStream $os) { $this->flushContents(); $blocks=512; $os->setReadPointer(0); while(false!==($read = $os->read($blocks))) $this->write($read); } /** * @see Swift_CharacterStream::importString() * * @param string $string */ public function importString($string) { $this->flushContents(); $this->write($string); } /** * @see Swift_CharacterStream::read() * * @param int $length * @return string */ public function read($length) { if ($this->_currentPos>=$this->_charCount) { return false; } $ret=false; $length = ($this->_currentPos+$length > $this->_charCount) ? $this->_charCount - $this->_currentPos : $length; switch ($this->_mapType) { case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: $len = $length*$this->_map; $ret = substr($this->_datas, $this->_currentPos * $this->_map, $len); $this->_currentPos += $length; break; case Swift_CharacterReader::MAP_TYPE_INVALID: $end = $this->_currentPos + $length; $end = $end > $this->_charCount ?$this->_charCount :$end; $ret = ''; for (; $this->_currentPos < $length; ++$this->_currentPos) { if (isset ($this->_map[$this->_currentPos])) { $ret .= '?'; } else { $ret .= $this->_datas[$this->_currentPos]; } } break; case Swift_CharacterReader::MAP_TYPE_POSITIONS: $end = $this->_currentPos + $length; $end = $end > $this->_charCount ?$this->_charCount :$end; $ret = ''; $start = 0; if ($this->_currentPos>0) { $start = $this->_map['p'][$this->_currentPos-1]; } $to = $start; for (; $this->_currentPos < $end; ++$this->_currentPos) { if (isset($this->_map['i'][$this->_currentPos])) { $ret .= substr($this->_datas, $start, $to - $start).'?'; $start = $this->_map['p'][$this->_currentPos]; } else { $to = $this->_map['p'][$this->_currentPos]; } } $ret .= substr($this->_datas, $start, $to - $start); break; } return $ret; } /** * @see Swift_CharacterStream::readBytes() * * @param int $length * @return int[] */ public function readBytes($length) { $read=$this->read($length); if ($read!==false) { $ret = array_map('ord', str_split($read, 1)); return $ret; } return false; } /** * @see Swift_CharacterStream::setPointer() * * @param int $charOffset */ public function setPointer($charOffset) { if ($this->_charCount<$charOffset) { $charOffset=$this->_charCount; } $this->_currentPos = $charOffset; } /** * @see Swift_CharacterStream::write() * * @param string $chars */ public function write($chars) { if (!isset($this->_charReader)) { $this->_charReader = $this->_charReaderFactory->getReaderFor( $this->_charset); $this->_map = array(); $this->_mapType = $this->_charReader->getMapType(); } $ignored=''; $this->_datas .= $chars; $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored); if ($ignored!==false) { $this->_datasSize=strlen($this->_datas)-strlen($ignored); } else { $this->_datasSize=strlen($this->_datas); } } } Swift-4.2.1/lib/classes/Swift/ConfigurableSpool.php100644 0 0 2526 12000050366 17363 0ustar 0 0 * * 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 int $limit The limit */ public function setMessageLimit($limit) { $this->_message_limit = (int) $limit; } /** * Gets the maximum number of messages to send per flush. * @return int The limit */ public function getMessageLimit() { return $this->_message_limit; } /** * Sets the time limit (in seconds) per flush. * @param int $limit The limit */ public function setTimeLimit($limit) { $this->_time_limit = (int) $limit; } /** * Gets the time limit (in seconds) per flush. * @return int The limit */ public function getTimeLimit() { return $this->_time_limit; } } Swift-4.2.1/lib/classes/Swift/DependencyContainer.php100644 0 0 23152 12000050366 17705 0ustar 0 0 _store); } /** * Test if an item is registered in this container with the given name. * @param string $itemName * @return boolean * @see register() */ public function has($itemName) { return array_key_exists($itemName, $this->_store) && isset($this->_store[$itemName]['lookupType']); } /** * Lookup the item with the given $itemName. * @param string $itemName * @return mixed * @throws Swift_DependencyException If the dependency is not found * @see register() */ 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. * * @param string $itemName * @return Swift_DependencyContainer * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() */ 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()}. * * @param string $className * @return Swift_DependencyContainer * @see withDependencies(), addConstructorValue(), addConstructorLookup() */ 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. * * @param array $lookups * @return Swift_DependencyContainer * @see addConstructorValue(), addConstructorLookup() */ 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. * * @param mixed $value * @return Swift_DependencyContainer * @see withDependencies(), addConstructorLookup() */ 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. * * @param string $lookup * @return Swift_DependencyContainer * @see withDependencies(), addConstructorValue() */ 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); } } } Swift-4.2.1/lib/classes/Swift/DependencyException.php100644 0 0 1116 12000050366 17675 0ustar 0 0 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) ); } } Swift-4.2.1/lib/classes/Swift/Encoder.php100644 0 0 1371 12000050366 15322 0ustar 0 0 = $maxLineLength || 76 < $maxLineLength) { $maxLineLength = 76; } $encodedString = base64_encode($string); $firstLine = ''; if (0 != $firstLineOffset) { $firstLine = substr( $encodedString, 0, $maxLineLength - $firstLineOffset ) . "\r\n"; $encodedString = substr( $encodedString, $maxLineLength - $firstLineOffset ); } return $firstLine . trim(chunk_split($encodedString, $maxLineLength, "\r\n")); } /** * Does nothing. */ public function charsetChanged($charset) { } } Swift-4.2.1/lib/classes/Swift/Encoder/QpEncoder.php100644 0 0 24543 12000050366 17230 0ustar 0 0 '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', 255 => '=FF' ); protected static $_safeMapShare = array(); /** * A map of non-encoded ascii characters. * @var string[] * @access protected */ protected $_safeMap = array(); /** * Creates a new QpEncoder for the given CharacterStream. * @param Swift_CharacterStream $charStream to use for reading characters * @param Swift_StreamFilter $filter if input should be canonicalized */ public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) { $this->_charStream = $charStream; if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) { $this->initSafeMap(); self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap; } else { $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()]; } $this->_filter = $filter; } public function __sleep() { return array('_charStream', '_filter'); } public function __wakeup() { if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) { $this->initSafeMap(); self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap; } else { $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()]; } } protected function getSafeMapShareId() { return get_class($this); } protected function initSafeMap() { foreach (array_merge( array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { $this->_safeMap[$byte] = chr($byte); } } /** * Takes an unencoded string and produces a QP encoded string from it. * QP encoded strings have a maximum line length of 76 characters. * If the first line needs to be shorter, indicate the difference with * $firstLineOffset. * @param string $string to encode * @param int $firstLineOffset, optional * @param int $maxLineLength, optional, 0 indicates the default of 76 chars * @return string */ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) { if ($maxLineLength > 76 || $maxLineLength <= 0) { $maxLineLength = 76; } $thisLineLength = $maxLineLength - $firstLineOffset; $lines = array(); $lNo = 0; $lines[$lNo] = ''; $currentLine =& $lines[$lNo++]; $size=$lineLen=0; $this->_charStream->flushContents(); $this->_charStream->importString($string); //Fetching more than 4 chars at one is slower, as is fetching fewer bytes // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes while (false !== $bytes = $this->_nextSequence()) { //If we're filtering the input if (isset($this->_filter)) { //If we can't filter because we need more bytes while ($this->_filter->shouldBuffer($bytes)) { //Then collect bytes into the buffer if (false === $moreBytes = $this->_nextSequence(1)) { break; } foreach ($moreBytes as $b) { $bytes[] = $b; } } //And filter them $bytes = $this->_filter->filter($bytes); } $enc = $this->_encodeByteSequence($bytes, $size); if ($currentLine && $lineLen+$size >= $thisLineLength) { $lines[$lNo] = ''; $currentLine =& $lines[$lNo++]; $thisLineLength = $maxLineLength; $lineLen=0; } $lineLen+=$size; $currentLine .= $enc; } return $this->_standardize(implode("=\r\n", $lines)); } /** * Updates the charset used. * @param string $charset */ public function charsetChanged($charset) { $this->_charStream->setCharacterSet($charset); } // -- Protected methods /** * Encode the given byte array into a verbatim QP form. * @param int[] $bytes * @return string * @access protected */ protected function _encodeByteSequence(array $bytes, &$size) { $ret = ''; $size=0; foreach ($bytes as $b) { if (isset($this->_safeMap[$b])) { $ret .= $this->_safeMap[$b]; ++$size; } else { $ret .= self::$_qpMap[$b]; $size+=3; } } return $ret; } /** * Get the next sequence of bytes to read from the char stream. * @param int $size number of bytes to read * @return int[] * @access protected */ 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 * @access protected */ 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; } } Swift-4.2.1/lib/classes/Swift/Encoder/Rfc2231Encoder.php100644 0 0 4347 12000050366 17652 0ustar 0 0 _charStream = $charStream; } /** * Takes an unencoded string and produces a string encoded according to * RFC 2231 from it. * @param string $string to encode * @param int $firstLineOffset * @param int $maxLineLength, optional, 0 indicates the default of 75 bytes * @return string */ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) { $lines = array(); $lineCount = 0; $lines[] = ''; $currentLine =& $lines[$lineCount++]; if (0 >= $maxLineLength) { $maxLineLength = 75; } $this->_charStream->flushContents(); $this->_charStream->importString($string); $thisLineLength = $maxLineLength - $firstLineOffset; while (false !== $char = $this->_charStream->read(4)) { $encodedChar = rawurlencode($char); if (0 != strlen($currentLine) && strlen($currentLine . $encodedChar) > $thisLineLength) { $lines[] = ''; $currentLine =& $lines[$lineCount++]; $thisLineLength = $maxLineLength; } $currentLine .= $encodedChar; } return implode("\r\n", $lines); } /** * Updates the charset used. * @param string $charset */ public function charsetChanged($charset) { $this->_charStream->setCharacterSet($charset); } } Swift-4.2.1/lib/classes/Swift/Encoding.php100644 0 0 2671 12000050366 15475 0ustar 0 0 lookup($key); } } Swift-4.2.1/lib/classes/Swift/Events/CommandEvent.php100644 0 0 2646 12000050366 17575 0ustar 0 0 _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 int[] */ public function getSuccessCodes() { return $this->_successCodes; } } Swift-4.2.1/lib/classes/Swift/Events/CommandListener.php100644 0 0 1136 12000050366 20272 0ustar 0 0 _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; } } Swift-4.2.1/lib/classes/Swift/Events/ResponseEvent.php100644 0 0 2474 12000050366 20014 0ustar 0 0 _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; } } Swift-4.2.1/lib/classes/Swift/Events/ResponseListener.php100644 0 0 1141 12000050366 20506 0ustar 0 0 _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. * @return int */ public function setResult($result) { $this->_result = $result; } /** * Get the result of this Event. * The return value is a bitmask from * {@link RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} * @return int */ public function getResult() { return $this->_result; } } Swift-4.2.1/lib/classes/Swift/Events/SendListener.php100644 0 0 1424 12000050366 17605 0ustar 0 0 _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); } } } Swift-4.2.1/lib/classes/Swift/Events/TransportChangeEvent.php100644 0 0 1122 12000050366 21305 0ustar 0 0 getSource(); } } Swift-4.2.1/lib/classes/Swift/Events/TransportChangeListener.php100644 0 0 2377 12000050366 22026 0ustar 0 0 _exception = $ex; } /** * Get the TransportException thrown. * @return Swift_TransportException */ public function getException() { return $this->_exception; } } Swift-4.2.1/lib/classes/Swift/Events/TransportExceptionListener.php100644 0 0 1232 12000050366 22564 0ustar 0 0 createDependenciesFor('transport.failover') ); $this->setTransports($transports); } /** * Create a new FailoverTransport instance. * @param string $transports * @return Swift_FailoverTransport */ public static function newInstance($transports = array()) { return new self($transports); } } Swift-4.2.1/lib/classes/Swift/FileSpool.php100644 0 0 12072 12000050366 15657 0ustar 0 0 * * 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 allready 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 anyreason a process is sending for too long * * @param int $timeout in second Defaults is for very slow smtp responses */ public function recover($timeout=900) { foreach (new DirectoryIterator($this->_path) as $file) { $file = $file->getRealPath(); if (substr($file, -16)=='.message.sending') { $lockedtime=filectime($file); if ((time()-$lockedtime)>$timeout) { rename($file, substr($file, 0, -8)); } } } } /** * Sends messages using the given transport instance. * * @param Swift_Transport $transport A transport instance * @param string[] &$failedRecipients An array of failures by-reference * * @return int The number of sent emails */ 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 int $count */ 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; } } Swift-4.2.1/lib/classes/Swift/FileStream.php100644 0 0 1012 12000050366 15766 0ustar 0 0 setFile( new Swift_ByteStream_FileByteStream($path) ); return $image; } } Swift-4.2.1/lib/classes/Swift/InputByteStream.php100644 0 0 3734 12000050366 17047 0ustar 0 0 _stream = $stream; } /** * Set a string into the cache under $itemKey for the namespace $nsKey. * @param string $nsKey * @param string $itemKey * @param string $string * @param int $mode * @see MODE_WRITE, MODE_APPEND */ 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. * @param string $nsKey * @param string $itemKey * @param Swift_OutputByteStream $os * @param int $mode * @see MODE_WRITE, MODE_APPEND */ 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 * @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 * @access private */ private function _prepareCache($nsKey) { if (!array_key_exists($nsKey, $this->_contents)) { $this->_contents[$nsKey] = array(); } } } Swift-4.2.1/lib/classes/Swift/KeyCache/DiskKeyCache.php100644 0 0 22044 12000050366 17726 0ustar 0 0 _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. * @param string $nsKey * @param string $itemKey * @param string $string * @param int $mode * @throws Swift_IoException * @see MODE_WRITE, MODE_APPEND */ 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. * @param string $nsKey * @param string $itemKey * @param Swift_OutputByteStream $os * @param int $mode * @see MODE_WRITE, MODE_APPEND * @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 * @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 * @access private */ private function _prepareCache($nsKey) { $cacheDir = $this->_path . '/' . $nsKey; if (!is_dir($cacheDir)) { if (!mkdir($cacheDir)) { throw new Swift_IoException('Failed to create cache directory ' . $cacheDir); } $this->_keys[$nsKey] = array(); } } /** * Get a file handle on the cache item. * @param string $nsKey * @param string $itemKey * @param int $position * @return resource * @access private */ 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); } } } Swift-4.2.1/lib/classes/Swift/KeyCache/DummyKeyCache.php100644 0 0 6232 12000050366 20110 0ustar 0 0 . */ /** * A basic KeyCache backed by an array. * @package Swift * @subpackage KeyCache * @author Xavier De Cock */ class Swift_KeyCache_DummyKeyCache implements Swift_KeyCache { /** * Set a string into the cache under $itemKey for the namespace $nsKey. * @param string $nsKey * @param string $itemKey * @param string $string * @param int $mode * @see MODE_WRITE, MODE_APPEND */ public function setString($nsKey, $itemKey, $string, $mode) { } /** * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. * @param string $nsKey * @param string $itemKey * @param Swift_OutputByteStream $os * @param int $mode * @see MODE_WRITE, MODE_APPEND */ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) { } /** * Provides a ByteStream which when written to, writes data to $itemKey. * NOTE: The stream will always write in append mode. * @param string $nsKey * @param string $itemKey * @return Swift_InputByteStream */ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) { return false; } /** * Get data back out of the cache as a string. * @param string $nsKey * @param string $itemKey * @return string */ public function getString($nsKey, $itemKey) { return false; } /** * 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) { return false; } /** * Check if the given $itemKey exists in the namespace $nsKey. * @param string $nsKey * @param string $itemKey * @return boolean */ public function hasKey($nsKey, $itemKey) { return false; } /** * Clear data for $itemKey in the namespace $nsKey if it exists. * @param string $nsKey * @param string $itemKey */ public function clearKey($nsKey, $itemKey) { } /** * Clear all data in the namespace $nsKey if it exists. * @param string $nsKey */ public function clearAll($nsKey) { } } Swift-4.2.1/lib/classes/Swift/KeyCache/KeyCacheInputStream.php100644 0 0 2226 12000050366 21267 0ustar 0 0 _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; } } Swift-4.2.1/lib/classes/Swift/LoadBalancedTransport.php100644 0 0 2256 12000050366 20154 0ustar 0 0 createDependenciesFor('transport.loadbalanced') ); $this->setTransports($transports); } /** * Create a new LoadBalancedTransport instance. * @param string $transports * @return Swift_LoadBalancedTransport */ public static function newInstance($transports = array()) { return new self($transports); } } Swift-4.2.1/lib/classes/Swift/MailTransport.php100644 0 0 2166 12000050366 16545 0ustar 0 0 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); } } Swift-4.2.1/lib/classes/Swift/Mailer.php100644 0 0 5403 12000050366 15154 0ustar 0 0 _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, optional * @return int */ public function send(Swift_Mime_Message $message, &$failedRecipients = null) { $failedRecipients = (array) $failedRecipients; if (!$this->_transport->isStarted()) { $this->_transport->start(); } $sent = 0; try { $sent = $this->_transport->send($message, $failedRecipients); } catch (Swift_RfcComplianceException $e) { foreach ($message->getTo() as $address => $name) { $failedRecipients[] = $address; } } return $sent; } /** * Register a plugin using a known unique key (e.g. myPlugin). * * @param Swift_Events_EventListener $plugin * @param string $key */ 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; } } Swift-4.2.1/lib/classes/Swift/Mailer/ArrayRecipientIterator.php100644 0 0 2346 12000050366 21612 0ustar 0 0 _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); } } Swift-4.2.1/lib/classes/Swift/Mailer/RecipientIterator.php100644 0 0 1410 12000050366 20602 0ustar 0 0 'Foo') or ('foo@bar' => NULL) * @return array */ public function nextRecipient(); } Swift-4.2.1/lib/classes/Swift/MemorySpool.php100644 0 0 3400 12000050366 16223 0ustar 0 0 * * 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 int The number of sent emails */ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) { if (!$this->messages) { return 0; } if (!$transport->isStarted()) { $transport->start(); } $count = 0; while ($message = array_pop($this->messages)) { $count += $transport->send($message, $failedRecipients); } return $count; } } Swift-4.2.1/lib/classes/Swift/Message.php100644 0 0 4347 12000050366 15335 0ustar 0 0 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_Mime_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 */ 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'); } } Swift-4.2.1/lib/classes/Swift/Mime/Attachment.php100644 0 0 7611 12000050366 16725 0ustar 0 0 setDisposition('attachment'); $this->setContentType('application/octet-stream'); $this->_mimeTypes = $mimeTypes; } /** * Get the nesting level used for this attachment. * Always returns {@link LEVEL_MIXED}. * @return int */ public function getNestingLevel() { return self::LEVEL_MIXED; } /** * Get the Content-Disposition of this attachment. * By default attachments have a disposition of "attachment". * @return string */ public function getDisposition() { return $this->_getHeaderFieldModel('Content-Disposition'); } /** * Set the Content-Disposition of this attachment. * @param string $disposition * @return Swift_Mime_Attachment */ public function setDisposition($disposition) { if (!$this->_setHeaderFieldModel('Content-Disposition', $disposition)) { $this->getHeaders()->addParameterizedHeader( 'Content-Disposition', $disposition ); } return $this; } /** * Get the filename of this attachment when downloaded. * @return string */ public function getFilename() { return $this->_getHeaderParameter('Content-Disposition', 'filename'); } /** * Set the filename of this attachment. * @param string $filename * @return Swift_Mime_Attachment */ public function setFilename($filename) { $this->_setHeaderParameter('Content-Disposition', 'filename', $filename); $this->_setHeaderParameter('Content-Type', 'name', $filename); return $this; } /** * Get the file size of this attachment. * @return int */ public function getSize() { return $this->_getHeaderParameter('Content-Disposition', 'size'); } /** * Set the file size of this attachment. * @param int $size * @return Swift_Mime_Attachment */ public function setSize($size) { $this->_setHeaderParameter('Content-Disposition', 'size', $size); return $this; } /** * Set the file that this attachment is for. * @param Swift_FileStream $file * @param string $contentType optional * @return Swift_Mime_Attachment */ public function setFile(Swift_FileStream $file, $contentType = null) { $this->setFilename(basename($file->getPath())); $this->setBody($file, $contentType); if (!isset($contentType)) { $extension = strtolower(substr( $file->getPath(), strrpos($file->getPath(), '.') + 1 )); if (array_key_exists($extension, $this->_mimeTypes)) { $this->setContentType($this->_mimeTypes[$extension]); } } return $this; } } Swift-4.2.1/lib/classes/Swift/Mime/CharsetObserver.php100644 0 0 1031 12000050366 17724 0ustar 0 0 = $maxLineLength || 76 < $maxLineLength) { $maxLineLength = 76; } $remainder = 0; while (false !== $bytes = $os->read(8190)) { $encoded = base64_encode($bytes); $encodedTransformed = ''; $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; while ($thisMaxLineLength < strlen($encoded)) { $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength) . "\r\n"; $firstLineOffset = 0; $encoded = substr($encoded, $thisMaxLineLength); $thisMaxLineLength = $maxLineLength; $remainder = 0; } if (0 < $remainingLength = strlen($encoded)) { $remainder += $remainingLength; $encodedTransformed .= $encoded; $encoded = null; } $is->write($encodedTransformed); } } /** * Get the name of this encoding scheme. * Returns the string 'base64'. * @return string */ public function getName() { return 'base64'; } } Swift-4.2.1/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php100644 0 0 3363 12000050366 24131 0ustar 0 0 read(8192)) { $string .= $bytes; } $is->write($this->encodeString($string)); } /** * Get the MIME name of this content encoding scheme. * @return string */ public function getName() { return 'quoted-printable'; } /** * Encode a given string to produce an encoded string. * @param string $string * @param int $firstLineOffset if first line needs to be shorter * @param int $maxLineLength - 0 indicates the default length for this encoding * @return string */ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) { return quoted_printable_encode($string); } } Swift-4.2.1/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php100644 0 0 10372 12000050366 23463 0ustar 0 0 _name = $name; $this->_canonical = $canonical; } /** * Encode a given string to produce an encoded string. * @param string $string * @param int $firstLineOffset, ignored * @param int $maxLineLength - 0 means no wrapping will occur * @return string */ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) { if ($this->_canonical) { $string = $this->_canonicalize($string); } return $this->_safeWordWrap($string, $maxLineLength, "\r\n"); } /** * Encode stream $in to stream $out. * @param Swift_OutputByteStream $in * @param Swift_InputByteStream $out * @param int $firstLineOffset, ignored * @param int $maxLineLength, optional, 0 means no wrapping will occur */ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) { $leftOver = ''; while (false !== $bytes = $os->read(8192)) { $toencode = $leftOver . $bytes; if ($this->_canonical) { $toencode = $this->_canonicalize($toencode); } $wrapped = $this->_safeWordWrap($toencode, $maxLineLength, "\r\n"); $lastLinePos = strrpos($wrapped, "\r\n"); $leftOver = substr($wrapped, $lastLinePos); $wrapped = substr($wrapped, 0, $lastLinePos); $is->write($wrapped); } if (strlen($leftOver)) { $is->write($leftOver); } } /** * Get the name of this encoding scheme. * @return string */ public function getName() { return $this->_name; } /** * Not used. */ public function charsetChanged($charset) { } // -- Private methods /** * A safer (but weaker) wordwrap for unicode. * @param string $string * @param int $length * @param string $le * @return string * @access private */ 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 * @access private */ private function _canonicalize($string) { return str_replace( array("\r\n", "\r", "\n"), array("\n", "\n", "\r\n"), $string ); } } Swift-4.2.1/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php100644 0 0 7525 12000050366 22766 0ustar 0 0 _dotEscape = $dotEscape; parent::__construct($charStream, $filter); } public function __sleep() { return array('_charStream', '_filter', '_dotEscape'); } protected function getSafeMapShareId() { return get_class($this).($this->_dotEscape ? '.dotEscape' : ''); } protected function initSafeMap() { parent::initSafeMap(); if ($this->_dotEscape) { /* Encode . as =2e for buggy remote servers */ unset($this->_safeMap[0x2e]); } } /** * Encode stream $in to stream $out. * QP encoded strings have a maximum line length of 76 characters. * If the first line needs to be shorter, indicate the difference with * $firstLineOffset. * @param Swift_OutputByteStream $os output stream * @param Swift_InputByteStream $is input stream * @param int $firstLineOffset * @param int $maxLineLength */ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) { if ($maxLineLength > 76 || $maxLineLength <= 0) { $maxLineLength = 76; } $thisLineLength = $maxLineLength - $firstLineOffset; $this->_charStream->flushContents(); $this->_charStream->importByteStream($os); $currentLine = ''; $prepend = ''; $size=$lineLen=0; while (false !== $bytes = $this->_nextSequence()) { //If we're filtering the input if (isset($this->_filter)) { //If we can't filter because we need more bytes while ($this->_filter->shouldBuffer($bytes)) { //Then collect bytes into the buffer if (false === $moreBytes = $this->_nextSequence(1)) { break; } foreach ($moreBytes as $b) { $bytes[] = $b; } } //And filter them $bytes = $this->_filter->filter($bytes); } $enc = $this->_encodeByteSequence($bytes, $size); if ($currentLine && $lineLen+$size >= $thisLineLength) { $is->write($prepend . $this->_standardize($currentLine)); $currentLine = ''; $prepend = "=\r\n"; $thisLineLength = $maxLineLength; $lineLen=0; } $lineLen+=$size; $currentLine .= $enc; } if (strlen($currentLine)) { $is->write($prepend . $this->_standardize($currentLine)); } } /** * Get the name of this encoding scheme. * Returns the string 'quoted-printable'. * @return string */ public function getName() { return 'quoted-printable'; } } Swift-4.2.1/lib/classes/Swift/Mime/EmbeddedFile.php100644 0 0 2373 12000050366 17126 0ustar 0 0 setDisposition('inline'); $this->setId($this->getId()); } /** * Get the nesting level of this EmbeddedFile. * Returns {@link LEVEL_RELATED}. * @return int */ public function getNestingLevel() { return self::LEVEL_RELATED; } } Swift-4.2.1/lib/classes/Swift/Mime/EncodingObserver.php100644 0 0 1130 12000050366 20061 0ustar 0 0 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 execatly 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 additonal 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; } } Swift-4.2.1/lib/classes/Swift/Mime/Header.php100644 0 0 3627 12000050366 16030 0ustar 0 0 getName(), "\r\n"); mb_internal_encoding($old); return $newstring; } return parent::encodeString($string, $firstLineOffset, $maxLineLength); } } Swift-4.2.1/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php100644 0 0 3675 12000050366 22324 0ustar 0 0 _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 Q encoded string from it. * @param string $string to encode * @param int $firstLineOffset, optional * @param int $maxLineLength, optional, 0 indicates the default of 76 chars * @return string */ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charst = 'utf-8') { return str_replace(array(' ', '=20', "=\r\n"), array('_', '_', "\r\n"), parent::encodeString($string, $firstLineOffset, $maxLineLength) ); } } Swift-4.2.1/lib/classes/Swift/Mime/HeaderFactory.php100644 0 0 3751 12000050366 17356 0ustar 0 0 setGrammar($grammar); } /** * Set the character set used in this Header. * @param string $charset */ public function setCharset($charset) { $this->clearCachedValueIf($charset != $this->_charset); $this->_charset = $charset; if (isset($this->_encoder)) { $this->_encoder->charsetChanged($charset); } } /** * Get the character set used in this Header. * @return string */ public function getCharset() { return $this->_charset; } /** * Set the language used in this Header. * For example, for US English, 'en-us'. * This can be unspecified. * @param string $lang */ public function setLanguage($lang) { $this->clearCachedValueIf($this->_lang != $lang); $this->_lang = $lang; } /** * Get the language used in this Header. * @return string */ public function getLanguage() { return $this->_lang; } /** * Set the encoder used for encoding the header. * @param Swift_Mime_HeaderEncoder $encoder */ public function setEncoder(Swift_Mime_HeaderEncoder $encoder) { $this->_encoder = $encoder; $this->setCachedValue(null); } /** * Get the encoder used for encoding this Header. * @return Swift_Mime_HeaderEncoder */ public function getEncoder() { return $this->_encoder; } /** * Set the grammar used for the header. * @param Swift_Mime_Grammar $grammar */ public function setGrammar(Swift_Mime_Grammar $grammar) { $this->_grammar = $grammar; $this->setCachedValue(null); } /** * Get the grammar used for this Header. * @return Swift_Mime_Grammar */ public function getGrammar() { return $this->_grammar; } /** * Get the name of this header (e.g. charset). * @return string */ public function getFieldName() { return $this->_name; } /** * Set the maximum length of lines in the header (excluding EOL). * @param int $lineLength */ public function setMaxLineLength($lineLength) { $this->clearCachedValueIf($this->_lineLength != $lineLength); $this->_lineLength = $lineLength; } /** * Get the maximum permitted length of lines in this Header. * @return int */ public function getMaxLineLength() { return $this->_lineLength; } /** * Get this Header rendered as a RFC 2822 compliant string. * @return string * @throws Swift_RfcComplianceException */ public function toString() { return $this->_tokensToString($this->toTokens()); } /** * Returns a string representation of this object. * * @return string * * @see toString() */ public function __toString() { return $this->toString(); } // -- Points of extension /** * Set the name of this Header field. * @param string $name * @access protected */ 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 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); //Forefully 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 to encode * @param int $firstLineOffset, optional * @return string */ protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) { //Adjust $firstLineOffset to account for space needed for syntax $charsetDecl = $this->_charset; if (isset($this->_lang)) { $charsetDecl .= '*' . $this->_lang; } $encodingWrapperLength = strlen( '=?' . $charsetDecl . '?' . $this->_encoder->getName() . '??=' ); if ($firstLineOffset >= 75) { //Does this logic need to be here? $firstLineOffset = 0; } $encodedTextLines = explode("\r\n", $this->_encoder->encodeString( $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset ) ); if (strtolower($this->_charset) !== 'iso-2022-jp') { // special encoding for iso-2022-jp using mb_encode_mimeheader foreach ($encodedTextLines as $lineNum => $line) { $encodedTextLines[$lineNum] = '=?' . $charsetDecl . '?' . $this->_encoder->getName() . '?' . $line . '?='; } } return implode("\r\n ", $encodedTextLines); } /** * Generates tokens from the given string which include CRLF as individual tokens. * @param string $token * @return string[] * @access protected */ protected function generateTokenLines($token) { return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE); } /** * Set a value into the cache. * @param string $value * @access protected */ protected function setCachedValue($value) { $this->_cachedValue = $value; } /** * Get the value in the cache. * @return string * @access protected */ protected function getCachedValue() { return $this->_cachedValue; } /** * Clear the cached value if $condition is met. * @param boolean $condition * @access protected */ 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 * @access protected */ 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 * @access private */ 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"; } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/DateHeader.php100644 0 0 5320 12000050366 20171 0ustar 0 0 * * * @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. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ public function getFieldType() { return self::TYPE_DATE; } /** * Set the model for the field body. * This method takes a UNIX timestamp. * @param int $model */ public function setFieldBodyModel($model) { $this->setTimestamp($model); } /** * Get the model for the field body. * This method returns a UNIX timestamp. * @return mixed */ public function getFieldBodyModel() { return $this->getTimestamp(); } /** * Get the UNIX timestamp of the Date in this Header. * @return int */ public function getTimestamp() { return $this->_timestamp; } /** * Set the UNIX timestamp of the Date in this Header. * @param int $timestamp */ public function setTimestamp($timestamp) { if (!is_null($timestamp)) { $timestamp = (int) $timestamp; } $this->clearCachedValueIf($this->_timestamp != $timestamp); $this->_timestamp = $timestamp; } /** * Get the string value of the body in this Header. * This is not necessarily RFC 2822 compliant since folding white space will * not be added at this stage (see {@link toString()} for that). * @return string * @see toString() */ public function getFieldBody() { if (!$this->getCachedValue()) { if (isset($this->_timestamp)) { $this->setCachedValue(date('r', $this->_timestamp)); } } return $this->getCachedValue(); } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/IdentificationHeader.php100644 0 0 10035 12000050366 22264 0ustar 0 0 setFieldName($name); parent::__construct($grammar); } /** * Get the type of Header that this instance represents. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ 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 {@link toString()} for that). * @return string * @see toString() * @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 . '>' ); } } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/MailboxHeader.php100644 0 0 22171 12000050366 20732 0ustar 0 0 setFieldName($name); $this->setEncoder($encoder); parent::__construct($grammar); } /** * Get the type of Header that this instance represents. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ 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 * )); * ?> * * @param string|string[] $mailboxes * @throws Swift_RfcComplianceException * @see __construct() * @see setAddresses() * @see setValue() */ 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 * // ) * ?> * * @return string[] * @throws Swift_RfcComplianceException * @see getNameAddresses() * @see toString() */ 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 * // ) * ?> * * @return string[] * @see getAddresses() * @see getNameAddressStrings() */ 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') * ); * ?> * * @param string[] $addresses * @throws Swift_RfcComplianceException * @see setNameAddresses() * @see setValue() */ public function setAddresses($addresses) { $this->setNameAddresses(array_values((array) $addresses)); } /** * Get all email addresses in this Header. * @return string[] * @see getNameAddresses() */ 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). * @return string * @throws Swift_RfcComplianceException * @see toString() */ 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[] * @access protected */ 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 * @access protected */ 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 * @access protected */ 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[] * @access private */ 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. * @access private */ 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.' ); } } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php100644 0 0 16467 12000050366 22146 0ustar 0 0 _paramEncoder = $paramEncoder; } /** * Get the type of Header that this instance represents. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ 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. * @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[] */ 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 * @access protected */ 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 * @access private */ 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 * @access private */ 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; } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/PathHeader.php100644 0 0 6653 12000050366 20222 0ustar 0 0 setFieldName($name); parent::__construct($grammar); } /** * Get the type of Header that this instance represents. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ 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). * @return string * @see toString() */ 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 invalid. * @access private */ 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.' ); } } } Swift-4.2.1/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php100644 0 0 4531 12000050366 22026 0ustar 0 0 setFieldName($name); $this->setEncoder($encoder); parent::__construct($grammar); } /** * Get the type of Header that this instance represents. * @return int * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX * @see TYPE_DATE, TYPE_ID, TYPE_PATH */ 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(); } } Swift-4.2.1/lib/classes/Swift/Mime/Message.php100644 0 0 13711 12000050366 16237 0ustar 0 0 '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(); } Swift-4.2.1/lib/classes/Swift/Mime/MimeEntity.php100644 0 0 5515 12000050366 16722 0ustar 0 0 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 * @param 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 * @param 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 * @param 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 * @param 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. * * @return int * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED */ 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 harset or install the mbstring or iconv extension).'); } return $string; } return $string; } } Swift-4.2.1/lib/classes/Swift/Mime/ParameterizedHeader.php100644 0 0 1242 12000050366 20534 0ustar 0 0 _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 $addresses * @return Swift_Mime_Header */ public function createMailboxHeader($name, $addresses = null) { $header = new Swift_Mime_Headers_MailboxHeader($name, $this->_encoder, $this->_grammar); if (isset($addresses)) { $header->setFieldBodyModel($addresses); } $this->_setHeaderCharset($header); return $header; } /** * Create a new Date header using $timestamp (UNIX time). * @param string $name * @param int $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); } } } Swift-4.2.1/lib/classes/Swift/Mime/SimpleHeaderSet.php100644 0 0 22653 12000050366 17676 0ustar 0 0 _factory = $factory; if (isset($charset)) { $this->setCharset($charset); } } /** * Set the charset used by these headers. * * @param string $charset */ public function setCharset($charset) { $this->_charset = $charset; $this->_factory->charsetChanged($charset); $this->_notifyHeadersOfCharset($charset); } /** * Add a new Mailbox Header with a list of $addresses. * * @param string $name * @param array|string $addresses */ public function addMailboxHeader($name, $addresses = null) { $this->_storeHeader($name, $this->_factory->createMailboxHeader($name, $addresses)); } /** * Add a new Date header using $timestamp (UNIX time). * * @param string $name * @param int $timestamp */ public function addDateHeader($name, $timestamp = null) { $this->_storeHeader($name, $this->_factory->createDateHeader($name, $timestamp)); } /** * Add a new basic text header with $name and $value. * * @param string $name * @param string $value */ public function addTextHeader($name, $value = null) { $this->_storeHeader($name, $this->_factory->createTextHeader($name, $value)); } /** * Add a new ParameterizedHeader with $name, $value and $params. * * @param string $name * @param string $value * @param array $params */ public function addParameterizedHeader($name, $value = null, $params = array()) { $this->_storeHeader($name, $this->_factory->createParameterizedHeader($name, $value, $params)); } /** * Add a new ID header for Message-ID or Content-ID. * * @param string $name * @param string|array $ids */ public function addIdHeader($name, $ids = null) { $this->_storeHeader($name, $this->_factory->createIdHeader($name, $ids)); } /** * Add a new Path header with an address (path) in it. * * @param string $name * @param string $path */ public function addPathHeader($name, $path = null) { $this->_storeHeader($name, $this->_factory->createPathHeader($name, $path)); } /** * Returns true if at least one header with the given $name exists. * * If multiple headers match, the actual one may be specified by $index. * * @param string $name * @param int $index * * @return 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 int $index */ public function set(Swift_Mime_Header $header, $index = 0) { $this->_storeHeader($header->getFieldName(), $header, $index); } /** * Get the header with the given $name. * * If multiple headers match, the actual one may be specified by $index. * Returns NULL if none present. * * @param string $name * @param int $index * * @return Swift_Mime_Header */ public function get($name, $index = 0) { if ($this->has($name, $index)) { $lowerName = strtolower($name); return $this->_headers[$lowerName][$index]; } } /** * Get all headers with the given $name. * * @param string $name * * @return array */ public function getAll($name = null) { if (!isset($name)) { $headers = array(); foreach ($this->_headers as $collection) { $headers = array_merge($headers, $collection); } return $headers; } $lowerName = strtolower($name); if (!array_key_exists($lowerName, $this->_headers)) { return array(); } return $this->_headers[$lowerName]; } /** * Remove the header with the given $name if it's set. * * If multiple headers match, the actual one may be specified by $index. * * @param string $name * @param int $index */ public function remove($name, $index = 0) { $lowerName = strtolower($name); unset($this->_headers[$lowerName][$index]); } /** * Remove all headers with the given $name. * * @param string $name */ public function removeAll($name) { $lowerName = strtolower($name); unset($this->_headers[$lowerName]); } /** * Create a new instance of this HeaderSet. * * @return Swift_Mime_HeaderSet */ public function newInstance() { return new self($this->_factory); } /** * Define a list of Header names as an array in the correct order. * * These Headers will be output in the given order where present. * * @param array $sequence */ public function defineOrdering(array $sequence) { $this->_order = array_flip(array_map('strtolower', $sequence)); } /** * Set a list of header names which must always be displayed when set. * * Usually headers without a field value won't be output unless set here. * * @param array $names */ public function setAlwaysDisplayed(array $names) { $this->_required = array_flip(array_map('strtolower', $names)); } /** * Notify this observer that the entity's charset has changed. * * @param string $charset */ public function charsetChanged($charset) { $this->setCharset($charset); } /** * Returns a string with a representation of all headers. * * @return string */ public function toString() { $string = ''; $headers = $this->_headers; if ($this->_canSort()) { uksort($headers, array($this, '_sortHeaders')); } foreach ($headers as $collection) { foreach ($collection as $header) { if ($this->_isDisplayed($header) || $header->getFieldBody() != '') { $string .= $header->toString(); } } } return $string; } /** * Returns a string representation of this object. * * @return string * * @see toString() */ public function __toString() { return $this->toString(); } // -- 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); } } } } Swift-4.2.1/lib/classes/Swift/Mime/SimpleMessage.php100644 0 0 41311 12000050366 17406 0ustar 0 0 getHeaders()->defineOrdering(array( 'Return-Path', 'Sender', 'Message-ID', 'Date', 'Subject', 'From', 'Reply-To', 'To', 'Cc', 'Bcc', 'MIME-Version', 'Content-Type', 'Content-Transfer-Encoding' )); $this->getHeaders()->setAlwaysDisplayed( array('Date', 'Message-ID', 'From') ); $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); $this->setDate(time()); $this->setId($this->getId()); $this->getHeaders()->addMailboxHeader('From'); } /** * Always returns {@link LEVEL_TOP} for a message instance. * @return int */ public function getNestingLevel() { return self::LEVEL_TOP; } /** * Set the subject of this message. * @param string $subject * @return Swift_Mime_SimpleMessage */ public function setSubject($subject) { if (!$this->_setHeaderFieldModel('Subject', $subject)) { $this->getHeaders()->addTextHeader('Subject', $subject); } return $this; } /** * Get the subject of this message. * @return string */ public function getSubject() { return $this->_getHeaderFieldModel('Subject'); } /** * Set the date at which this message was created. * @param int $date * @return Swift_Mime_SimpleMessage */ public function setDate($date) { if (!$this->_setHeaderFieldModel('Date', $date)) { $this->getHeaders()->addDateHeader('Date', $date); } return $this; } /** * Get the date at which this message was created. * @return int */ public function getDate() { return $this->_getHeaderFieldModel('Date'); } /** * Set the return-path (the bounce address) of this message. * @param string $address * @return Swift_Mime_SimpleMessage */ public function setReturnPath($address) { if (!$this->_setHeaderFieldModel('Return-Path', $address)) { $this->getHeaders()->addPathHeader('Return-Path', $address); } return $this; } /** * Get the return-path (bounce address) of this message. * @return string */ public function getReturnPath() { return $this->_getHeaderFieldModel('Return-Path'); } /** * Set the sender of this message. * This does not override the From field, but it has a higher significance. * @param string $sender * @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 */ 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 array $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 array $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 array $addresses * @param string $name optional * @return Swift_Mime_SimpleMessage */ public function setBcc($addresses, $name = null) { if (!is_array($addresses) && isset($name)) { $addresses = array($addresses => $name); } if (!$this->_setHeaderFieldModel('Bcc', (array) $addresses)) { $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); } return $this; } /** * Get the Bcc addresses of this message. * * @return array */ public function getBcc() { return $this->_getHeaderFieldModel('Bcc'); } /** * Set the priority of this message. * The value is an integer where 1 is the highest priority and 5 is the lowest. * @param int $priority * @return Swift_Mime_SimpleMessage */ public function setPriority($priority) { $priorityMap = array( 1 => 'Highest', 2 => 'High', 3 => 'Normal', 4 => 'Low', 5 => 'Lowest' ); $pMapKeys = array_keys($priorityMap); if ($priority > max($pMapKeys)) { $priority = max($pMapKeys); } elseif ($priority < min($pMapKeys)) { $priority = min($pMapKeys); } if (!$this->_setHeaderFieldModel('X-Priority', sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { $this->getHeaders()->addTextHeader('X-Priority', sprintf('%d (%s)', $priority, $priorityMap[$priority])); } return $this; } /** * Get the priority of this message. * The returned value is an integer where 1 is the highest priority and 5 * is the lowest. * @return int */ public function getPriority() { list($priority) = sscanf($this->_getHeaderFieldModel('X-Priority'), '%[1-5]' ); return isset($priority) ? $priority : 3; } /** * Ask for a delivery receipt from the recipient to be sent to $addresses * @param array $addresses * @return Swift_Mime_SimpleMessage */ public function setReadReceiptTo($addresses) { if (!$this->_setHeaderFieldModel('Disposition-Notification-To', $addresses)) { $this->getHeaders() ->addMailboxHeader('Disposition-Notification-To', $addresses); } return $this; } /** * Get the addresses to which a read-receipt will be sent. * @return string */ public function getReadReceiptTo() { return $this->_getHeaderFieldModel('Disposition-Notification-To'); } /** * Attach a {@link Swift_Mime_MimeEntity} such as an Attachment or MimePart. * @param Swift_Mime_MimeEntity $entity * @return Swift_Mime_SimpleMessage */ public function attach(Swift_Mime_MimeEntity $entity) { $this->setChildren(array_merge($this->getChildren(), array($entity))); return $this; } /** * Remove an already attached entity. * @param Swift_Mime_MimeEntity $entity * @return Swift_Mime_SimpleMessage */ public function detach(Swift_Mime_MimeEntity $entity) { $newChildren = array(); foreach ($this->getChildren() as $child) { if ($entity !== $child) { $newChildren[] = $child; } } $this->setChildren($newChildren); return $this; } /** * Attach a {@link Swift_Mime_MimeEntity} and return it's CID source. * This method should be used when embedding images or other data in a message. * @param Swift_Mime_MimeEntity $entity * @return string */ public function embed(Swift_Mime_MimeEntity $entity) { $this->attach($entity); return 'cid:' . $entity->getId(); } /** * Get this message as a complete string. * @return string */ public function toString() { if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') { $this->setChildren(array_merge(array($this->_becomeMimePart()), $children)); $string = parent::toString(); $this->setChildren($children); } else { $string = parent::toString(); } return $string; } /** * Returns a string representation of this object. * * @return string * * @see toString() */ 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; } } Swift-4.2.1/lib/classes/Swift/Mime/SimpleMimeEntity.php100644 0 0 55265 12000050366 20123 0ustar 0 0 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. * @return int * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE */ 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 int */ public function getMaxLineLength() { return $this->_maxLineLength; } /** * Set the maximum line length of lines in this body. * Though not enforced by the library, lines should not exceed 1000 chars. * @param int $length * @return Swift_Mime_SimpleMimeEntity */ public function setMaxLineLength($length) { $this->_maxLineLength = $length; return $this; } /** * Get all children added to this entity. * @return array of Swift_Mime_Entity */ public function getChildren() { return $this->_children; } /** * Set all children of this entity. * @param array $children Swiift_Mime_Entity instances * @param int $compoundLevel For internal use only * @return Swift_Mime_SimpleMimeEntity */ public function setChildren(array $children, $compoundLevel = null) { //TODO: Try to refactor this logic $compoundLevel = isset($compoundLevel) ? $compoundLevel : $this->_getCompoundLevel($children) ; $immediateChildren = array(); $grandchildren = array(); $newContentType = $this->_userContentType; foreach ($children as $child) { $level = $this->_getNeededChildLevel($child, $compoundLevel); if (empty($immediateChildren)) { //first iteration $immediateChildren = array($child); } else { $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel); if ($nextLevel == $level) { $immediateChildren[] = $child; } elseif ($level < $nextLevel) { //Re-assign immediateChildren to grandchilden $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 accomodate 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 * @throws Swift_RfcComplianceException * @return Swift_Mime_SimpleMimeEntity */ 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(); 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. * * @return string * * @see toString() */ public function __toString() { return $this->toString(); } /** * Write this entire entity to a {@link Swift_InputByteStream}. * @param Swift_InputByteStream */ public function toByteStream(Swift_InputByteStream $is) { $is->write($this->_headers->toString()); $is->commit(); 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. */ 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 . '>' ); } } } Swift-4.2.1/lib/classes/Swift/MimePart.php100644 0 0 3037 12000050366 15462 0ustar 0 0 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); } } Swift-4.2.1/lib/classes/Swift/NullTransport.php100644 0 0 1630 12000050366 16570 0ustar 0 0 * * 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(); } } Swift-4.2.1/lib/classes/Swift/OutputByteStream.php100644 0 0 2171 12000050366 17242 0ustar 0 0 setThreshold($threshold); $this->setSleepTime($sleep); $this->_sleeper = $sleeper; } /** * Set the number of emails to send before restarting. * @param int $threshold */ public function setThreshold($threshold) { $this->_threshold = $threshold; } /** * Get the number of emails to send before restarting. * @return int */ public function getThreshold() { return $this->_threshold; } /** * Set the number of seconds to sleep for during a restart. * @param int $sleep time */ public function setSleepTime($sleep) { $this->_sleep = $sleep; } /** * Get the number of seconds to sleep for during a restart. * @return int */ public function getSleepTime() { return $this->_sleep; } /** * Invoked immediately before the Message is sent. * @param Swift_Events_SendEvent $evt */ public function beforeSendPerformed(Swift_Events_SendEvent $evt) { } /** * Invoked immediately after the Message is sent. * @param Swift_Events_SendEvent $evt */ public function sendPerformed(Swift_Events_SendEvent $evt) { ++$this->_counter; if ($this->_counter >= $this->_threshold) { $transport = $evt->getTransport(); $transport->stop(); if ($this->_sleep) { $this->sleep($this->_sleep); } $transport->start(); $this->_counter = 0; } } /** * Sleep for $seconds. * @param int $seconds */ public function sleep($seconds) { if (isset($this->_sleeper)) { $this->_sleeper->sleep($seconds); } else { sleep($seconds); } } } Swift-4.2.1/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php100644 0 0 7076 12000050366 22027 0ustar 0 0 getMessage(); $message->toByteStream($this); } /** * Invoked immediately following a command being sent. * @param Swift_Events_ResponseEvent $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; } } Swift-4.2.1/lib/classes/Swift/Plugins/Decorator/Replacements.php100644 0 0 1447 12000050366 21734 0ustar 0 0 * $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; } } } Swift-4.2.1/lib/classes/Swift/Plugins/ImpersonatePlugin.php100644 0 0 3345 12000050366 21034 0ustar 0 0 _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'); } } } Swift-4.2.1/lib/classes/Swift/Plugins/Logger.php100644 0 0 1200 12000050366 16572 0ustar 0 0 _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_ResponseEvent $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); } } Swift-4.2.1/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php100644 0 0 2452 12000050366 21205 0ustar 0 0 _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); } } Swift-4.2.1/lib/classes/Swift/Plugins/Loggers/EchoLogger.php100644 0 0 2137 12000050366 21005 0ustar 0 0 _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() { } } Swift-4.2.1/lib/classes/Swift/Plugins/MessageLogger.php100644 0 0 2643 12000050366 20113 0ustar 0 0 messages = array(); } /** * Get the message list * * @return array */ public function getMessages() { return $this->messages; } /** * Get the message count * * @return int count */ public function countMessages() { return count($this->messages); } /** * Empty the message list * */ public function clear() { $this->messages = array(); } /** * Invoked immediately before the Message is sent. * * @param Swift_Events_SendEvent $evt */ public function beforeSendPerformed(Swift_Events_SendEvent $evt) { $this->messages[] = clone $evt->getMessage(); } /** * Invoked immediately after the Message is sent. * * @param Swift_Events_SendEvent $evt */ public function sendPerformed(Swift_Events_SendEvent $evt) { } } Swift-4.2.1/lib/classes/Swift/Plugins/Pop/Pop3Connection.php100644 0 0 1372 12000050366 20764 0ustar 0 0 _host = $host; $this->_port = $port; $this->_crypto = $crypto; } /** * Create a new PopBeforeSmtpPlugin for $host and $port. * * @param string $host * @param int $port * @param string $cypto 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 */ public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) { $this->_connection = $connection; return $this; } /** * Bind this plugin to a specific SMTP transport instance. * * @param Swift_Transport */ public function bindSmtp(Swift_Transport $smtp) { $this->_transport = $smtp; } /** * Set the connection timeout in seconds (default 10). * * @param int $timeout */ public function setTimeout($timeout) { $this->_timeout = (int) $timeout; return $this; } /** * Set the username to use when connecting (if needed). * * @param string $username */ public function setUsername($username) { $this->_username = $username; return $this; } /** * Set the password to use when connecting (if needed). * * @param string $password */ 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; } } Swift-4.2.1/lib/classes/Swift/Plugins/RedirectingPlugin.php100644 0 0 5254 12000050366 21006 0ustar 0 0 _recipient = $recipient; } /** * Set the recipient of all messages. * @param int $threshold */ public function setRecipient($recipient) { $this->_recipient = $recipient; } /** * Get the recipient of all messages. * @return int */ public function getRecipient() { return $this->_recipient; } /** * 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()); // replace them with the one to send to $message->setTo($this->_recipient); $headers->removeAll('Cc'); $headers->removeAll('Bcc'); } /** * 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'); } } } Swift-4.2.1/lib/classes/Swift/Plugins/Reporter.php100644 0 0 1554 12000050366 17171 0ustar 0 0 _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) ); } } } Swift-4.2.1/lib/classes/Swift/Plugins/Reporters/HitReporter.php100644 0 0 2674 12000050366 21627 0ustar 0 0 _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(); } } Swift-4.2.1/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php100644 0 0 2342 12000050366 21777 0ustar 0 0 " . PHP_EOL; echo "PASS " . $address . PHP_EOL; echo "" . PHP_EOL; flush(); } else { echo "
" . PHP_EOL; echo "FAIL " . $address . PHP_EOL; echo "
" . PHP_EOL; flush(); } } } Swift-4.2.1/lib/classes/Swift/Plugins/Sleeper.php100644 0 0 716 12000050366 16745 0ustar 0 0 _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; if (self::BYTES_PER_MINUTE == $this->_mode) { $sleep = $this->_throttleBytesPerMinute($duration); } else { $sleep = $this->_throttleMessagesPerMinute($duration); } if ($sleep > 0) { $this->sleep($sleep); } } /** * Invoked when a Message is sent. * @param Swift_Events_SendEvent $evt */ public function sendPerformed(Swift_Events_SendEvent $evt) { parent::sendPerformed($evt); ++$this->_messages; } /** * Sleep for $seconds. * @param int $seconds */ public function sleep($seconds) { if (isset($this->_sleeper)) { $this->_sleeper->sleep($seconds); } else { sleep($seconds); } } /** * Get the current UNIX timestamp * @return int */ public function getTimestamp() { if (isset($this->_timer)) { return $this->_timer->getTimestamp(); } else { return time(); } } // -- Private methods /** * Get a number of seconds to sleep for. * @param int $timePassed * @return int * @access private */ 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 * @access private */ private function _throttleMessagesPerMinute($timePassed) { $expectedDuration = $this->_messages / ($this->_rate / 60); return (int) ceil($expectedDuration - $timePassed); } } Swift-4.2.1/lib/classes/Swift/Plugins/Timer.php100644 0 0 711 12000050366 16421 0ustar 0 0 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; } /** * Add the * @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; } } Swift-4.2.1/lib/classes/Swift/ReplacementFilterFactory.php100644 0 0 1102 12000050366 20670 0ustar 0 0 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); } } Swift-4.2.1/lib/classes/Swift/SmtpTransport.php100644 0 0 2553 12000050366 16606 0ustar 0 0 createDependenciesFor('transport.smtp') ); $this->setHost($host); $this->setPort($port); $this->setEncryption($security); } /** * Create a new SmtpTransport instance. * @param string $host * @param int $port * @param string $security * @return Swift_SmtpTransport */ public static function newInstance($host = 'localhost', $port = 25, $security = null) { return new self($host, $port, $security); } } Swift-4.2.1/lib/classes/Swift/Spool.php100644 0 0 2325 12000050366 15037 0ustar 0 0 * * 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 int The number of sent emails */ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null); } Swift-4.2.1/lib/classes/Swift/SpoolTransport.php100644 0 0 2066 12000050366 16756 0ustar 0 0 * * 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); } } Swift-4.2.1/lib/classes/Swift/StreamFilter.php100644 0 0 1312 12000050366 16337 0ustar 0 0 _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 * @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; } } Swift-4.2.1/lib/classes/Swift/StreamFilters/StringReplacementFilter.php100644 0 0 3003 12000050366 23315 0ustar 0 0 _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); } } Swift-4.2.1/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php100644 0 0 2400 12000050366 24645 0ustar 0 0 _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]; } } Swift-4.2.1/lib/classes/Swift/SwiftException.php100644 0 0 1015 12000050366 16711 0ustar 0 0 _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 sourceIp * @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 to collect 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 * @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(); } } Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php100644 0 0 4230 12000050366 23710 0ustar 0 0 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; } } Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php100644 0 0 2566 12000050366 23542 0ustar 0 0 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; } } } Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php100644 0 0 2455 12000050366 23532 0ustar 0 0 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; } } } Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/AuthHandler.php100644 0 0 13565 12000050366 21256 0ustar 0 0 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 * @access protected */ 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'); } } Swift-4.2.1/lib/classes/Swift/Transport/Esmtp/Authenticator.php100644 0 0 1535 12000050366 21643 0ustar 0 0 . * @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 * @param boolean &$stop to be set true 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(); } Swift-4.2.1/lib/classes/Swift/Transport/EsmtpTransport.php100644 0 0 24434 12000050366 20771 0ustar 0 0 'tcp', 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'blocking' => 1, 'tls' => false, 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET ); /** * Creates a new EsmtpTransport using the given I/O buffer. * @param Swift_Transport_IoBuffer $buf * @param Swift_Transport_EsmtpHandler[] $extensionHandlers * @param Swift_Events_EventDispatcher $dispatcher */ public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher) { parent::__construct($buf, $dispatcher); $this->setExtensionHandlers($extensionHandlers); } /** * Set the host to connect to. * @param string $host * @return Swift_Transport_EsmtpTransport */ public function setHost($host) { $this->_params['host'] = $host; return $this; } /** * Get the host to connect to. * @return string */ public function getHost() { return $this->_params['host']; } /** * Set the port to connect to. * @param int $port * @return Swift_Transport_EsmtpTransport */ public function setPort($port) { $this->_params['port'] = (int) $port; return $this; } /** * Get the port to connect to. * @return int */ public function getPort() { return $this->_params['port']; } /** * Set the connection timeout. * @param int $timeout seconds * @return Swift_Transport_EsmtpTransport */ public function setTimeout($timeout) { $this->_params['timeout'] = (int) $timeout; $this->_buffer->setParam('timeout', (int) $timeout); return $this; } /** * Get the connection timeout. * @return int */ public function getTimeout() { return $this->_params['timeout']; } /** * Set the encryption type (tls or ssl) * @param string $encryption * @return Swift_Transport_EsmtpTransport */ public function setEncryption($enc) { if ('tls' == $enc) { $this->_params['protocol'] = 'tcp'; $this->_params['tls'] = true; } else { $this->_params['protocol'] = $enc; $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 sourceIp * @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 * @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()); } } Swift-4.2.1/lib/classes/Swift/Transport/FailoverTransport.php100644 0 0 4373 12000050366 21430 0ustar 0 0 _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(); } } Swift-4.2.1/lib/classes/Swift/Transport/IoBuffer.php100644 0 0 3165 12000050366 17443 0ustar 0 0 _transports = $transports; $this->_deadTransports = array(); } /** * Get $transports to delegate to. * * @return array 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 to collect 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 * @access protected */ 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. * * @access protected */ protected function _killCurrentTransport() { if ($transport = array_pop($this->_transports)) { try { $transport->stop(); } catch (Exception $e) { } $this->_deadTransports[] = $transport; } } } Swift-4.2.1/lib/classes/Swift/Transport/MailInvoker.php100644 0 0 1420 12000050366 20152 0ustar 0 0 _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 to collect 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; } } Swift-4.2.1/lib/classes/Swift/Transport/NullTransport.php100644 0 0 4004 12000050366 20562 0ustar 0 0 * * 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 to collect failures by-reference * * @return int The number of sent emails */ public function send(Swift_Mime_Message $message, &$failedRecipients = null) { if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); if ($evt->bubbleCancelled()) { return 0; } } if ($evt) { $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); } return 0; } /** * Register a plugin. * * @param Swift_Events_EventListener $plugin */ public function registerPlugin(Swift_Events_EventListener $plugin) { $this->_eventDispatcher->bindEventListener($plugin); } } Swift-4.2.1/lib/classes/Swift/Transport/SendmailTransport.php100644 0 0 11623 12000050366 21431 0ustar 0 0 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 to collect 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; } } Swift-4.2.1/lib/classes/Swift/Transport/SimpleMailInvoker.php100644 0 0 2761 12000050366 21335 0ustar 0 0 . */ /** * This is the implementation class for {@link Swift_Transport_MailInvoker}. * * @package Swift * @subpackage Transport * @author Chris Corbyn */ class Swift_Transport_SimpleMailInvoker implements Swift_Transport_MailInvoker { /** * Send mail via the mail() function. * * This method takes the same arguments as PHP mail(). * * @param string $to * @param string $subject * @param string $body * @param string $headers * @param string $extraParams * * @return boolean */ public function mail($to, $subject, $body, $headers = null, $extraParams = null) { if (!ini_get('safe_mode')) { return @mail($to, $subject, $body, $headers, $extraParams); } else { return @mail($to, $subject, $body, $headers); } } } Swift-4.2.1/lib/classes/Swift/Transport/SmtpAgent.php100644 0 0 1676 12000050366 17651 0ustar 0 0 * * 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 to collect failures by-reference * * @return int The number of sent emails */ public function send(Swift_Mime_Message $message, &$failedRecipients = null) { if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); if ($evt->bubbleCancelled()) { return 0; } } $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); } } Swift-4.2.1/lib/classes/Swift/Transport/StreamBuffer.php100644 0 0 21545 12000050366 20351 0ustar 0 0 _replacementFactory = $replacementFactory; } /** * Perform any initialization needed, using the given $params. * Parameters will vary depending upon the type of IoBuffer used. * @param array $params */ public function initialize(array $params) { $this->_params = $params; switch ($params['type']) { case self::TYPE_PROCESS: $this->_establishProcessConnection(); break; case self::TYPE_SOCKET: default: $this->_establishSocketConnection(); break; } } /** * Set an individual param on the buffer (e.g. switching to SSL). * @param string $param * @param mixed $value */ public function setParam($param, $value) { if (isset($this->_stream)) { switch ($param) { case 'timeout': if ($this->_stream) { stream_set_timeout($this->_stream, $value); } break; case 'blocking': if ($this->_stream) { stream_set_blocking($this->_stream, 1); } } } $this->_params[$param] = $value; } public function startTLS() { return stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); } /** * Perform any shutdown logic needed. */ public function terminate() { if (isset($this->_stream)) { switch ($this->_params['type']) { case self::TYPE_PROCESS: fclose($this->_in); fclose($this->_out); proc_close($this->_stream); break; case self::TYPE_SOCKET: default: fclose($this->_stream); break; } } $this->_stream = null; $this->_out = null; $this->_in = null; } /** * Set an array of string replacements which should be made on data written * to the buffer. This could replace LF with CRLF for example. * @param string[] $replacements */ public function setWriteTranslations(array $replacements) { foreach ($this->_translations as $search => $replace) { if (!isset($replacements[$search])) { $this->removeFilter($search); unset($this->_translations[$search]); } } foreach ($replacements as $search => $replace) { if (!isset($this->_translations[$search])) { $this->addFilter( $this->_replacementFactory->createFilter($search, $replace), $search ); $this->_translations[$search] = true; } } } /** * Get a line of output (including any CRLF). * The $sequence number comes from any writes and may or may not be used * depending upon the implementation. * @param int $sequence of last write to scan from * @return string */ public function readLine($sequence) { if (isset($this->_out) && !feof($this->_out)) { $line = fgets($this->_out); if (strlen($line)==0) { $metas = stream_get_meta_data($this->_out); if ($metas['timed_out']) { throw new Swift_IoException( 'Connection to ' . $this->_getReadConnectionDescription() . ' Timed Out' ); } } return $line; } } /** * Reads $length bytes from the stream into a string and moves the pointer * through the stream by $length. If less bytes exist than are requested the * remaining bytes are given instead. If no bytes are remaining at all, boolean * false is returned. * @param int $length * @return string */ 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. * @access private */ 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. * @access private */ 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; } } } Swift-4.2.1/lib/classes/Swift/TransportException.php100644 0 0 1153 12000050366 17614 0ustar 0 0 */ class Swift_Validate { /** * Grammar Object * @var Swift_Mime_Grammar */ private static $grammar = null; /** * Checks if an email matches the current grammars * @param string $email */ 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 ); } } Swift-4.2.1/lib/dependency_maps/cache_deps.php100644 0 0 1204 12000050366 16421 0ustar 0 0 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') ; Swift-4.2.1/lib/dependency_maps/message_deps.php100644 0 0 313 12000050366 16762 0ustar 0 0 register('message.message') -> asNewInstanceOf('Swift_Message') -> register('message.mimepart') -> asNewInstanceOf('Swift_MimePart') ; Swift-4.2.1/lib/dependency_maps/mime_deps.php100644 0 0 7033 12000050366 16313 0ustar 0 0 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.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')) ; unset($swift_mime_types); Swift-4.2.1/lib/dependency_maps/transport_deps.php100644 0 0 4345 12000050366 17423 0ustar 0 0 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') ; Swift-4.2.1/lib/mime_types.php100644 0 0 4712 12000050366 13367 0ustar 0 0 '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' ); Swift-4.2.1/lib/preferences.php100644 0 0 2031 12000050366 13505 0ustar 0 0 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. if (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); Swift-4.2.1/lib/swift_init.php100644 0 0 1335 12000050366 13371 0ustar 0 0 dump() should be used for output where needed. Will address this again later. Swift-4.2.1/test-suite/LICENSE100644 0 0 16727 12000050366 13101 0ustar 0 0 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. Swift-4.2.1/test-suite/README100644 0 0 14342 12000050366 12743 0ustar 0 0 Sweety SimpleTest Suite ----------------------- Sweety is a wrapper around SimpleTest's XML reporting capabilities which makes unit tests easier to manage and friendlier to run. Tests are run in a grouped fashion, but each individual test runs in its own environment and own memory space either via forking new PHP processes, or by making new HTTP requests. Sweety works with any vanilla version of SimpleTest since the XmlReporter was added. Tests can be run on command line, in an AJAX equipped web browser*, or in a web browser with javascript turned off. * Sweety has been tested with success in the following browsers: - Mozilla Firefox 2.0 - Safari 3-beta - Internet Explorer 7 - Opera 9 Configuring Sweety: -------------------- All Sweety configuration is contained inside the config.php file, defined as constants for the mostpart. Make sure you at least indicate a path to a directory containing SimpleTest, and also change the SWEETY_INCLUDE_PATH and SWEETY_TEST_PATH to fit your needs. Paths are provided using the directory separator for your OS. Use the PHP constant PATH_SEPARATOR if you need to run in different environments. If you have test cases in directories /webdev/tests/unit and /webdev/tests/integration your SWEETY_TEST_PATH should look like: define('SWEETY_TEST_PATH', '/webdev/tests/unit' . PATH_SEPARATOR . '/webdev/tests/integration'); If you want to run Sweety on the command line you'll need to specify the path to your PHP executable (typically /usr/bin/php). Sweety needs to be able to fork new processes using this executable. What to do if your naming scheme doesn't use PEAR conventions: -------------------------------------------------------------- By default Sweety looks for classes using PEAR naming conventions. If you use some other naming convention you need to tell Sweety how to find your test cases. This is a two step process: 1) Write a new Sweety_TestLocator -- don't worry, it's easy! Refer to the interface in lib/Sweety/TestLocator.php for guidance on what your TestLocator needs to include (just two methods for searching and including). 2) Add it to your config.php. Once you've written a new TestLocator which works for your naming scheme, change the config value SWEETY_TEST_LOCATOR to the name of your new class, then include the class file somewhere inside the config.php. If you use multiple class naming conventions, list your TestLocators as a comma separated string. Making tests appear in Sweety's interface: ------------------------------------------- No really, you just edit the configuration and they'll show up if a TestLocator can find them ;) Running sweety on the command line: ----------------------------------- Interacting with Sweety on the command line you'll get almost as much detail as you do in a web browser, although the formatting obviously isn't so pretty! All operations are handled by the file named run.php in the sweety installation directory. -bash$ php run.php #runs all tests -bash$ php run.php Name_Of_TestClass #runs a single test case -bash$ php run.php Name_Of_TestClass xml #runs a single test case in XML Runing Sweety with AJAX: ------------------------- Open up an AJAX equipped web browsers (preferably supporting DOM 3 XPath, but at least support basic DOM). Navigate to the index.php file at the installation directory of Sweety. You'll see the screen is divided into two sections, left and right. On the left there's a list of test cases which you can click to run. On the right you get all the verbose output from running the tests. Clicking the "Run Tests" button will run all tests you can currently see in the list. As each test runs, a request is sent to the web server to get SimpleTest to run your test case. If the test passes the test case will turn green, if it fails it will turn red. Tests go yellow until a final conclusion is drawn. If you need to stop the tests at any time just click the button again (it should say "Stop Tests" whilst the tests run). Whilst the tests run, the large bar to the right of the screen will tally up aggregated results and will eventually go either green or red indicating a pass or failure. Failed assertion messages will appear in the page just like they do with the HtmlReporter of SimpleTest. Clicking a single test case will run just that test in isolation. If you want (or need?) to run the test with SimpleTest's HtmlReporter just click the HTML Icon (little world image) next to the test case. Tests can also be run in XML if needed. Above the list of tests there's a filter box which can be directly typed into. Typing in here narrows down the list of testcases to show only the ones which match the search query. Refreshing the page with your browser's refresh button will reset the test suite. When you change your code, you DO NOT need to refesh your browser window. Just click the "Run Tests" button, or click the individual test to refresh the results. If you add a new test case you will need to refresh your browser window however. Running Sweety without JavaScript: ---------------------------------- If your web browser has JavaScript disabled you can still use the HTML version of the test suite. Open up the index.php file in your web browser. You'll see the screen is divided into two sections, left and right. On the left there's a list of test cases with checkboxes next to them which you can check to run. On the right you get all the verbose output from running the tests. Clicking the "Run Tests" button will run all the currently selected test cases. This could take a long time depending upon how many tests you have to run, but once complete you'll see the page again where the tests you selected will either be red or green indicating a pass or failure. The bar at the right of the screen will contain aggregate results for all the tests and will be either red or green to indicate an overall pass or failure. Assertion messages appear in the page just like with SimpleTest's HtmlReporter. If you want to run just a single test case, click the "Run" icon at the right of the test (little running man image). You can run tests with SimpleTest's HtmlReporter by clicking the HTML icon (little world image) next to the test case. Tests can be run in XML if needed too. Enjoy! Swift-4.2.1/test-suite/config.php100644 0 0 4621 12000050366 14020 0ustar 0 0 setReporter(new Sweety_Reporter_HtmlReporter()); $runner->setIgnoredClassRegex(SWEETY_IGNORED_CLASSES); $locators = preg_split('/\s*,\s*/', SWEETY_TEST_LOCATOR); foreach ($locators as $locator) { $runner->registerTestLocator(new $locator()); } if (isset($_GET['test'])) { $testName = $_GET['test']; $format = isset($_GET['format']) ? $_GET['format'] : Sweety_Runner::REPORT_HTML; $runner->runTestCase($testName, $format); } else { $runner->runAllTests(); } Swift-4.2.1/test-suite/lib/Sweety/Reporter.php100644 0 0 2457 12000050366 16410 0ustar 0 0 _name = $name; $this->_aggregates = array( 'cases' => 0, 'run' => 0, 'passes' => 0, 'fails' => 0, 'exceptions' => 0 ); } /** * Used so test case reporters can notify this reporter when they've completed. * @param string $testCase */ public function notifyEnded($testCase) { $this->_aggregates['run']++; } /** * Get the reporter used to report on this specific test case. * @param string $testCase * @return Sweety_Reporter */ public function getReporterFor($testCase) { $this->_aggregates['cases']++; $reporter = new Sweety_Reporter_CliTestCaseReporter($testCase, $this); return $reporter; } /** * Returns true if start() has been invoked. * @return boolean */ public function isStarted() { return $this->_started; } /** * Start reporting. */ public function start() { $this->_started = true; echo $this->_name . PHP_EOL; } /** * Report a skipped test case. * @param string $message * @param string $path */ public function reportSkip($message, $path) { echo " \033[34m\033[1m\033[4mSkip\033[0m:"; $messageLines = explode(PHP_EOL, wordwrap($message, 74, PHP_EOL)); foreach ($messageLines as $line) { echo ' ' . $line . PHP_EOL; } echo ' in: ' . $path . PHP_EOL; } /** * Report a passing assertion. * @param string $message * @param string $path */ public function reportPass($message, $path) { $this->_aggregates['passes']++; } /** * Report a failing assertion. * @param string $message * @param string $path */ public function reportFail($message, $path) { $this->_aggregates['fails']++; echo "\033[31m" . $this->_aggregates['fails'] . ') '; echo $message . "\033[0m" . PHP_EOL; echo ' in: ' . $path . PHP_EOL; } /** * Report an unexpected exception. * @param string $message * @param string $path */ public function reportException($message, $path) { $this->_aggregates['exceptions']++; echo "\033[31m\033[1mException" . $this->_aggregates['exceptions'] . "\033[0m!" . PHP_EOL; echo "\033[1m" . $message . "\033[0m" . PHP_EOL; echo ' in ' . $path . PHP_EOL; } /** * Report output from something like a dump(). * @param string $output * @param string $path */ public function reportOutput($output, $path) { if (preg_match('/^\{image @ (.*?)\}$/D', $output, $matches)) { echo " \033[33mSmoke Test\033[0m" . PHP_EOL; echo ' Compare email sent with image @ ' . $matches[1] . PHP_EOL; } else { echo '--------------------' . PHP_EOL; echo $output . PHP_EOL; echo '--------------------' . PHP_EOL; } } /** * End reporting. */ public function finish() { $this->_started = false; $incomplete = $this->_aggregates['cases'] - $this->_aggregates['run']; if ($incomplete) { echo '**********************' . PHP_EOL; echo $incomplete . ' test case(s) did not complete.' . PHP_EOL . 'This may be because invalid XML was output during the test run' . PHP_EOL . 'and/or because an error occured.' . PHP_EOL . 'Try running the tests separately for more detail.' . PHP_EOL; echo '**********************' . PHP_EOL; } $success = (!$this->_aggregates['fails'] && !$this->_aggregates['exceptions'] && $this->_aggregates['cases'] == $this->_aggregates['run']); if ($success) { echo "\033[32m\033[1mOK\033[0m" . PHP_EOL; } else { echo "\033[31m\033[1mFAILURES!!!\033[0m" . PHP_EOL; } echo 'Test cases run: '; echo $this->_aggregates['run'] . '/' . $this->_aggregates['cases'] . ', '; echo 'Passes: ' . $this->_aggregates['passes'] . ', '; echo 'Failures: ' . $this->_aggregates['fails'] . ', '; echo 'Exceptions: '. $this->_aggregates['exceptions'] . PHP_EOL; exit((int) !$success); } } Swift-4.2.1/test-suite/lib/Sweety/Reporter/CliTestCaseReporter.php100644 0 0 6402 12000050366 22270 0ustar 0 0 _parent = $parent; $this->_testCase = $testCase; $this->_aggregates = array( 'passes' => 0, 'fails' => 0, 'exceptions' => 0 ); } /** * Get the reporter used to report on this specific test case. * This method is stubbed only to return itself. * @param string $testCase * @return Sweety_Reporter */ public function getReporterFor($testCase) { return $this; } /** * Returns true if start() has been invoked. * @return boolean */ public function isStarted() { return $this->_started; } /** * Start reporting. */ public function start() { $this->_started = true; } /** * Report a skipped test case. * @param string $message * @param string $path */ public function reportSkip($message, $path) { $this->_parent->reportSkip($message, $path); } /** * Report a passing assertion. * @param string $message * @param string $path */ public function reportPass($message, $path) { $this->_aggregates['passes']++; $this->_parent->reportPass($message, $path); } /** * Report a failing assertion. * @param string $message * @param string $path */ public function reportFail($message, $path) { $this->_aggregates['fails']++; $this->_parent->reportFail($message, $path); } /** * Report an unexpected exception. * @param string $message * @param string $path */ public function reportException($message, $path) { $this->_aggregates['exceptions']++; $this->_parent->reportException($message, $path); } /** * Report output from something like a dump(). * @param string $output * @param string $path */ public function reportOutput($output, $path) { $this->_parent->reportOutput($output, $path); } /** * End reporting. */ public function finish() { $this->_started = false; if (!$this->_aggregates['fails'] && !$this->_aggregates['exceptions']) { echo ' >> ' . $this->_testCase . ' '; echo "\033[32mOK\033[0m" . PHP_EOL; } else { echo ' !! ' . $this->_testCase . ' '; echo "\033[31mFAILED\033[0m" . PHP_EOL; } $this->_parent->notifyEnded($this->_testCase); } } Swift-4.2.1/test-suite/lib/Sweety/Reporter/HtmlReporter.php100644 0 0 7314 12000050366 21034 0ustar 0 0 _tplVars =& $vars; } /** * Used so test case reporters can notify this reporter when they've completed. * @param string $testCase */ public function notifyEnded($testCase) { $this->_tplVars['runTests'][] = $testCase; $this->_tplVars['runCount']++; } /** * Get the reporter used to report on this specific test case. * @param string $testCase * @return Sweety_Reporter */ public function getReporterFor($testCase) { $this->_tplVars['caseCount']++; $reporter = new Sweety_Reporter_HtmlTestCaseReporter($testCase, $this); $reporter->setTemplateVars($this->_tplVars); return $reporter; } /** * Returns true if start() has been invoked. * @return boolean */ public function isStarted() { return $this->_started; } /** * Start reporting. */ public function start() { $this->_started = true; } /** * Report a skipped test case. * @param string $message * @param string $path */ public function reportSkip($message, $path) { $this->_tplVars['messages'][] = array( 'type' => 'skip', 'path' => $path, 'text' => $message); } /** * Report a passing assertion. * @param string $message * @param string $path */ public function reportPass($message, $path) { $this->_tplVars['passCount']++; } /** * Report a failing assertion. * @param string $message * @param string $path */ public function reportFail($message, $path) { $this->_tplVars['failCount']++; $this->_tplVars['messages'][] = array( 'type' => 'fail', 'path' => $path, 'text' => $message); } /** * Report an unexpected exception. * @param string $message * @param string $path */ public function reportException($message, $path) { $this->_tplVars['exceptionCount']++; $this->_tplVars['messages'][] = array( 'type' => 'exception', 'path' => $path, 'text' => $message); } /** * Report output from something like a dump(). * @param string $output * @param string $path */ public function reportOutput($output, $path) { $this->_tplVars['messages'][] = array( 'type' => 'output', 'path' => $path, 'text' => $output); } /** * End reporting. */ public function finish() { $this->_started = false; if (!$this->_tplVars['failCount'] && !$this->_tplVars['exceptionCount'] && $this->_tplVars['caseCount'] == $this->_tplVars['runCount']) { $this->_tplVars['result'] = 'pass'; } else { $this->_tplVars['result'] = 'fail'; } $incomplete = $this->_tplVars['caseCount'] - $this->_tplVars['runCount']; if (0 < $incomplete) { $this->_tplVars['messages'][] = array( 'type' => 'internal', 'path' => '', 'text' => $incomplete . ' test case(s) did not complete.' . ' This may be because invalid XML was output during the test run' . ' and/or because an error occured.' . ' Incomplete test cases are shown in yellow. Click the HTML link ' . 'next to the test for more detail.' ); } } } Swift-4.2.1/test-suite/lib/Sweety/Reporter/HtmlTestCaseReporter.php100644 0 0 6750 12000050366 22473 0ustar 0 0 _parent = $parent; $this->_testCase = $testCase; $this->_aggregates = array( 'passes' => 0, 'fails' => 0, 'exceptions' => 0 ); } /** * Set template data. * @param mixed[] */ public function setTemplateVars(&$vars) { $this->_tplVars =& $vars; } /** * Get the reporter used to report on this specific test case. * This method is stubbed only to return itself. * @param string $testCase * @return Sweety_Reporter */ public function getReporterFor($testCase) { return $this; } /** * Returns true if start() has been invoked. * @return boolean */ public function isStarted() { return $this->_started; } /** * Start reporting. */ public function start() { $this->_started = true; $this->_tplVars['runTests'][$this->_testCase] = 'running'; } /** * Report a skipped test case. * @param string $message * @param string $path */ public function reportSkip($message, $path) { $this->_parent->reportSkip($message, $path); } /** * Report a passing assertion. * @param string $message * @param string $path */ public function reportPass($message, $path) { $this->_aggregates['passes']++; $this->_parent->reportPass($message, $path); } /** * Report a failing assertion. * @param string $message * @param string $path */ public function reportFail($message, $path) { $this->_aggregates['fails']++; $this->_parent->reportFail($message, $path); } /** * Report an unexpected exception. * @param string $message * @param string $path */ public function reportException($message, $path) { $this->_aggregates['exceptions']++; $this->_parent->reportException($message, $path); } /** * Report output from something like a dump(). * @param string $output * @param string $path */ public function reportOutput($output, $path) { $this->_parent->reportOutput($output, $path); } /** * End reporting. */ public function finish() { $this->_started = false; if (!$this->_aggregates['fails'] && !$this->_aggregates['exceptions']) { $this->_tplVars['runTests'][$this->_testCase] = 'pass'; } else { $this->_tplVars['runTests'][$this->_testCase] = 'fail'; } $this->_parent->notifyEnded($this->_testCase); } } Swift-4.2.1/test-suite/lib/Sweety/Runner.php100644 0 0 2517 12000050366 16054 0ustar 0 0 _reporter = $reporter; } /** * Get the reporter used for showing results. * @return Sweety_Reporter */ public function getReporter() { return $this->_reporter; } /** * Register a test locator instance. * @param Sweety_TestLocator $locator */ public function registerTestLocator(Sweety_TestLocator $locator) { $this->_testLocators[] = $locator; } /** * Set the regular expression used to filter out certain class names. * @param string $ignoredClassRegex */ public function setIgnoredClassRegex($ignoredClassRegex) { $this->_ignoredClassRegex = $ignoredClassRegex; } /** * Get the filtering regular expression for ignoring certain classes. * @return string */ public function getIgnoredClassRegex() { return $this->_ignoredClassRegex; } /** * Run a single test case with the given name, using the provided output format. * @param string $testName * @param string $format (xml, text or html) * @return int */ public function runTestCase($testName, $format = Sweety_Runner::REPORT_TEXT) { foreach ($this->_testLocators as $locator) { if ($locator->includeTest($testName)) { break; } } $testClass = new ReflectionClass($testName); if ($testClass->getConstructor()) { //We don't want test output to be cached if (!SimpleReporter::inCli()) { header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); } switch ($format) { case Sweety_Runner::REPORT_HTML: $reporter = new HtmlReporter(); break; case Sweety_Runner::REPORT_XML: if (!SimpleReporter::inCli()) { header("Content-Type: text/xml"); //Sigh! SimpleTest (skip() issues). } $reporter = new XmlReporter(); break; case Sweety_Runner::REPORT_TEXT: default: $reporter = new TextReporter(); break; } $test = $testClass->newInstance(); return $test->run($reporter) ? 0 : 1; } return 1; } /** * Use strategies to find tests which are runnable. * @param string[] $dirs * @return string[] */ protected function findTests($dirs = array()) { $tests = array(); foreach ($this->_testLocators as $locator) { $tests += $locator->getTests($dirs); } return $tests; } /** * Parse an XML response from a test case an report to the reporter. * @param string $xml * @param string $testCase */ protected function parseXml($xml, $testCase) { $reporter = $this->_reporter->getReporterFor($testCase); if (!$reporter->isStarted()) { $reporter->start(); } $xml = str_replace("\0", '?', trim($xml)); $xml = preg_replace('/[^\x01-\x7F]/e', 'sprintf("&#%d;", ord("$0"));', $xml); //Do something better? if (!empty($xml)) { $document = @simplexml_load_string($xml); if ($document) { $this->_parseDocument($document, $testCase, $reporter); $reporter->finish(); return; } } $reporter->reportException( 'Invalid XML response: ' . trim(strip_tags( preg_replace('/^\s*<\?xml.+<\/(?:name|pass|fail|exception)>/s', '', $xml) )), $testCase ); } /** * Parse formatted test output. * @param SimpleXMLElement The node containing the output * @param string $path to this test method * @access private */ private function _parseFormatted(SimpleXMLElement $formatted, $path = '', Sweety_Reporter $reporter) { $reporter->reportOutput((string)$formatted, $path); } /** * Parse test output. * @param SimpleXMLElement The node containing the output * @param string $path to this test method * @access private */ private function _parseMessage(SimpleXMLElement $message, $path = '', Sweety_Reporter $reporter) { $reporter->reportOutput((string)$message, $path); } /** * Parse a test failure. * @param SimpleXMLElement The node containing the fail * @param string $path to this test method * @access private */ private function _parseFailure(SimpleXMLElement $failure, $path = '', Sweety_Reporter $reporter) { $reporter->reportFail((string)$failure, $path); } /** * Parse an exception. * @param SimpleXMLElement The node containing the exception * @param string $path to this test method * @access private */ private function _parseException(SimpleXMLElement $exception, $path = '', Sweety_Reporter $reporter) { $reporter->reportException((string)$exception, $path); } /** * Parse a pass. * @param SimpleXMLElement The node containing this pass. * @param string $path to this test method * @access private */ private function _parsePass(SimpleXMLElement $pass, $path = '', Sweety_Reporter $reporter) { $reporter->reportPass((string)$pass, $path); } /** * Parse a single test case. * @param SimpleXMLElement The node containing the test case * @param string $path to this test case * @access private */ private function _parseTestCase(SimpleXMLElement $testCase, $path = '', Sweety_Reporter $reporter) { foreach ($testCase->xpath('./test') as $testMethod) { $testMethodName = (string) $this->_firstNodeValue($testMethod->xpath('./name')); foreach ($testMethod->xpath('./formatted') as $formatted) { $this->_parseFormatted( $formatted, $path . ' -> ' . $testMethodName, $reporter); } foreach ($testMethod->xpath('./message') as $message) { $this->_parseMessage( $message, $path . ' -> ' . $testMethodName, $reporter); } foreach ($testMethod->xpath('./fail') as $failure) { $this->_parseFailure( $failure, $path . ' -> ' . $testMethodName, $reporter); } foreach ($testMethod->xpath('./exception') as $exception) { $this->_parseException( $exception, $path . ' -> ' . $testMethodName, $reporter); } foreach ($testMethod->xpath('./pass') as $pass) { $this->_parsePass($pass, $path . ' -> ' . $testMethodName, $reporter); } $stdout = trim((string) $testMethod); if ($stdout) { $reporter->reportOutput($stdout, $path . ' -> ' . $testMethodName); } } } /** * Parse the results of all tests. * @param SimpleXMLElement The node containing the tests * @param string $path to the tests * @access private */ private function _parseResults(SimpleXMLElement $document, $path = '', Sweety_Reporter $reporter) { $groups = $document->xpath('./group'); if (!empty($groups)) { foreach ($groups as $group) { $groupName = (string) $this->_firstNodeValue($group->xpath('./name')); $this->_parseResults($group, $path . ' -> ' . $groupName, $reporter); } } else { foreach ($document->xpath('./case') as $testCase) { $this->_parseTestCase($testCase, $path, $reporter); } } } /** * Parse the entire SimpleTest XML document from a test case. * @param SimpleXMLElement $document to parse * @param string $path to the test * @access private */ private function _parseDocument(SimpleXMLElement $document, $path = '', Sweety_Reporter $reporter) { if ($everything = $this->_firstNodeValue($document->xpath('/run'))) { $this->_parseResults($everything, $path, $reporter); } elseif ($skip = $this->_firstNodeValue($document->xpath('/skip'))) { $reporter->reportSkip((string) $skip, $path); } } protected function _sort($a, $b) { $apkg = preg_replace('/_[^_]+$/D', '', $a); $bpkg = preg_replace('/_[^_]+$/D', '', $b); if ($apkg == $bpkg) { if ($a == $b) { return 0; } else { return ($a > $b) ? 1 : -1; } } else { return ($apkg > $bpkg) ? 1 : -1; } } private function _firstNodeValue($nodeSet) { $first = array_shift($nodeSet); return $first; } } Swift-4.2.1/test-suite/lib/Sweety/Runner/CliRunner.php100644 0 0 5113 12000050366 17750 0ustar 0 0 _dirs = $dirs; $this->_command = $command; } /** * Runs all test cases found under the given directories. * @param string[] $directories to scan for test cases * @param string To be prepended to class names * @return int */ public function runAllTests($dirs = array()) { if (empty($dirs)) { $dirs = $this->_dirs; } $reporter = $this->getReporter(); if (!$reporter->isStarted()) { $reporter->start(); } $tests = $this->findTests($dirs); usort($tests, array($this, '_sort')); global $argv; if (!empty($argv[1])) { if (substr($argv[1], 0, 1) == '!') { $argv[1] = substr($argv[1], 1); foreach ($tests as $index => $name) { if (@preg_match($argv[1] . 'i', $name)) { unset($tests[$index]); } } } else { foreach ($tests as $index => $name) { if (!@preg_match($argv[1] . 'i', $name)) { unset($tests[$index]); } } } } $ret = $this->_runTestList($tests); $reporter->finish(); return $ret; } /** * Run all possible tests from the given list. * @param string[] $tests * @return int */ protected function _runTestList(array $tests) { foreach ($tests as $testCase) { if (preg_match($this->getIgnoredClassRegex(), $testCase)) { continue; } $command = $this->_command; $command .= ' ' . $testCase; $command .= ' ' . Sweety_Runner::REPORT_XML; exec($command, $output, $status); $xml = implode(PHP_EOL, $output); $this->parseXml($xml, $testCase); unset($status); unset($output); } return 0; } } Swift-4.2.1/test-suite/lib/Sweety/Runner/HtmlRunner.php100644 0 0 7256 12000050366 20157 0ustar 0 0 _dirs = $dirs; $this->_template = $template; $this->_name = $name; } /** * Runs all test cases found under the given directories. * @param string[] $directories to scan for test cases * @param string To be prepended to class names * @return int */ public function runAllTests($dirs = array()) { //We don't want test output to be cached header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); if (empty($dirs)) { $dirs = $this->_dirs; } $testCases = $this->findTests($dirs); foreach ($testCases as $k => $testCase) { if (preg_match($this->getIgnoredClassRegex(), $testCase)) { unset($testCases[$k]); } } usort($testCases, array($this, '_sort')); $vars = array( //String 'testCases' => $testCases, //String 'suiteName' => $this->_name, // testCase => pass | fail | running 'runTests' => array(), //Integer 'caseCount' => 0, //Integer 'runCount' => 0, //Integer 'passCount' => 0, //Integer 'failCount' => 0, //Integer 'exceptionCount' => 0, // type => pass | fail | exception | output | internal, path => testCase, text => ... 'messages' => array(), // pass | fail 'result' => 'idle' ); if (isset($_REQUEST['runtests'])) { $reporter = $this->getReporter(); $reporter->setTemplateVars($vars); if (!$reporter->isStarted()) { $reporter->start(); } $this->_runTestList((array)$_REQUEST['runtests'], $reporter); $reporter->finish(); } else { foreach ($testCases as $testCase) { $vars['runTests'][$testCase] = 'idle'; //Show all checked by default } } $this->_render($vars); } /** * Run tests in the given array using the REST API (kind of). * @param string[] $tests * @param Sweety_Reporter $reporter * @return int */ protected function _runTestList(array $tests, Sweety_Reporter $reporter) { $protocol = !empty($_SERVER['HTTPS']) ? 'https://' : 'http://'; //Most likely a HTTP/1.0 server not supporting HOST header $server = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '127.0.0.1'; $path = '/'; if (!empty($_SERVER['REQUEST_URI'])) { $path = preg_replace('/\?.*$/sD', '', $_SERVER['REQUEST_URI']); } $baseUrl = $protocol . $server . $path; foreach ($tests as $testCase) { $url = $baseUrl . '?test=' . $testCase . '&format=xml'; $xml = file_get_contents($url); $this->parseXml($xml, $testCase); } return 0; } /** * Renders the view for the suite. * @param string[] $templateVars */ protected function _render($vars = array()) { foreach ($vars as $k => $v) { $$k = $v; } require_once $this->_template; } } Swift-4.2.1/test-suite/lib/Sweety/TestLocator.php100644 0 0 743 12000050366 17025 0ustar 0 0 _findTestCases($dirs); } public function includeTest($testCase) { $file = str_replace('_', '/', $testCase) . '.php'; foreach (explode(PATH_SEPARATOR, get_include_path()) as $dir) { if (is_file($dir . '/' . $file)) { require_once $dir . '/' . $file; return true; } } return false; } protected function _findTestCases($dirs = array(), $prepend = '') { $ret = array(); foreach ($dirs as $dir) { if (array_key_exists($dir, $this->_testCache)) { $ret += $this->_testCache[$dir]; continue; } $this->_testCache[$dir] = array(); $handle = opendir($dir); while (false !== $file = readdir($handle)) { if (substr($file, 0, 1) != '.' && is_dir($dir . '/' . $file)) { foreach ($this->_findTestCases( array($dir . '/' . $file), $prepend . $file . '_') as $add) { $this->_testCache[$dir][] = $add; $ret[] = $add; } } elseif (substr($file, -4) == '.php') { $className = $prepend . basename($file, '.php'); $this->_testCache[$dir][] = $className; $ret[] = $className; } } closedir($handle); } sort($ret); return $ret; } } Swift-4.2.1/test-suite/lib/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE100644 0 0 34170 12000050366 21745 0ustar 0 0 Simple Test interface changes ============================= Because the SimpleTest tool set is still evolving it is likely that tests written with earlier versions will fail with the newest ones. The most dramatic changes are in the alpha releases. Here is a list of possible problems and their fixes... Fatal error: Call to undefined method Classname::classname() ------------------------------------------------------------ SimpleTest renamed all of its constructors from Classname to __construct; derived classes invoking their parent constructors should replace parent::Classname() with parent::__construct(). Custom CSS in HtmlReporter not being applied -------------------------------------------- Batch rename of protected and private methods means that _getCss() was renamed to getCss(); replace your function definition accordingly. setReturnReference() throws errors in E_STRICT ---------------------------------------------- Happens when an object is passed by reference. This also happens with setReturnReferenceAt(). If you want to return objects then replace these with calls to returns() and returnsAt() with the same arguments. This change was forced in the 1.1 version for E_STRICT compatibility. assertReference() throws errors in E_STRICT ------------------------------------------- Due to language restrictions you cannot compare both variables and objects in E_STRICT mode. Use assertSame() in this mode with objects. This change was forced the 1.1 version. Cannot create GroupTest ----------------------- The GroupTest has been renamed TestSuite (see below). It was removed completely in 1.1 in favour of this name. No method getRelativeUrls() or getAbsoluteUrls() ------------------------------------------------ These methods were always a bit weird anyway, and the new parsing of the base tag makes them more so. They have been replaced with getUrls() instead. If you want the old functionality then simply chop off the current domain from getUrl(). Method setWildcard() removed in mocks ------------------------------------- Even setWildcard() has been removed in 1.0.1beta now. If you want to test explicitely for a '*' string, then simply pass in new IdenticalExpectation('*') instead. No method _getTest() on mocks ----------------------------- This has finally been removed. It was a pretty esoteric flex point anyway. It was there to allow the mocks to work with other test tools, but no one does this. No method assertError(), assertNoErrors(), swallowErrors() ---------------------------------------------------------- These have been deprecated in 1.0.1beta in favour of expectError() and expectException(). assertNoErrors() is redundant if you use expectError() as failures are now reported immediately. No method TestCase::signal() ---------------------------- This has been deprecated in favour of triggering an error or throwing an exception. Deprecated as of 1.0.1beta. No method TestCase::sendMessage() --------------------------------- This has been deprecated as of 1.0.1beta. Failure to connect now emits failures ------------------------------------- It used to be that you would have to use the getTransferError() call on the web tester to see if there was a socket level error in a fetch. This check is now always carried out by the WebTestCase unless the fetch is prefaced with WebTestCase::ignoreErrors(). The ignore directive only lasts for test case fetching action such as get() and click(). No method SimpleTestOptions::ignore() ------------------------------------- This is deprecated in version 1.0.1beta and has been moved to SimpleTest::ignore() as that is more readable. In addition, parent classes are also ignored automatically. If you are using PHP5 you can skip this directive simply by marking your test case as abstract. No method assertCopy() ---------------------- This is deprecated in 1.0.1 in favour of assertClone(). The assertClone() method is slightly different in that the objects must be identical, but without being a reference. It is thus not a strict inversion of assertReference(). Constructor wildcard override has no effect in mocks ---------------------------------------------------- As of 1.0.1beta this is now set with setWildcard() instead of in the constructor. No methods setStubBaseClass()/getStubBaseClass() ------------------------------------------------ As mocks are now used instead of stubs, these methods stopped working and are now removed as of the 1.0.1beta release. The mock objects may be freely used instead. No method addPartialMockCode() ------------------------------ The ability to insert arbitrary partial mock code has been removed. This was a low value feature causing needless complications. It was removed in the 1.0.1beta release. No method setMockBaseClass() ---------------------------- The ability to change the mock base class has been scheduled for removal and is deprecated since the 1.0.1beta version. This was a rarely used feature except as a workaround for PHP5 limitations. As these limitations are being resolved it's hoped that the bundled mocks can be used directly. No class Stub ------------- Server stubs are deprecated from 1.0.1 as the mocks now have exactly the same interface. Just use mock objects instead. No class SimpleTestOptions -------------------------- This was replced by the shorter SimpleTest in 1.0.1beta1 and is since deprecated. No file simple_test.php ----------------------- This was renamed test_case.php in 1.0.1beta to more accurately reflect it's purpose. This file should never be directly included in test suites though, as it's part of the underlying mechanics and has a tendency to be refactored. No class WantedPatternExpectation --------------------------------- This was deprecated in 1.0.1alpha in favour of the simpler name PatternExpectation. No class NoUnwantedPatternExpectation ------------------------------------- This was deprecated in 1.0.1alpha in favour of the simpler name NoPatternExpectation. No method assertNoUnwantedPattern() ----------------------------------- This has been renamed to assertNoPattern() in 1.0.1alpha and the old form is deprecated. No method assertWantedPattern() ------------------------------- This has been renamed to assertPattern() in 1.0.1alpha and the old form is deprecated. No method assertExpectation() ----------------------------- This was renamed as assert() in 1.0.1alpha and the old form has been deprecated. No class WildcardExpectation ---------------------------- This was a mostly internal class for the mock objects. It was renamed AnythingExpectation to bring it closer to JMock and NMock in version 1.0.1alpha. Missing UnitTestCase::assertErrorPattern() ------------------------------------------ This method is deprecated for version 1.0.1 onwards. This method has been subsumed by assertError() that can now take an expectation. Simply pass a PatternExpectation into assertError() to simulate the old behaviour. No HTML when matching page elements ----------------------------------- This behaviour has been switched to using plain text as if it were seen by the user of the browser. This means that HTML tags are suppressed, entities are converted and whitespace is normalised. This should make it easier to match items in forms. Also images are replaced with their "alt" text so that they can be matched as well. No method SimpleRunner::_getTestCase() -------------------------------------- This was made public as getTestCase() in 1.0RC2. No method restartSession() -------------------------- This was renamed to restart() in the WebTestCase, SimpleBrowser and the underlying SimpleUserAgent in 1.0RC2. Because it was undocumented anyway, no attempt was made at backward compatibility. My custom test case ignored by tally() -------------------------------------- The _assertTrue method has had it's signature changed due to a bug in the PHP 5.0.1 release. You must now use getTest() from within that method to get the test case. Mock compatibility with other unit testers is now deprecated as of 1.0.1alpha as PEAR::PHPUnit2 should soon have mock support of it's own. Broken code extending SimpleRunner ---------------------------------- This was replaced with SimpleScorer so that I could use the runner name in another class. This happened in RC1 development and there is no easy backward compatibility fix. The solution is simply to extend SimpleScorer instead. Missing method getBaseCookieValue() ----------------------------------- This was renamed getCurrentCookieValue() in RC1. Missing files from the SimpleTest suite --------------------------------------- Versions of SimpleTest prior to Beta6 required a SIMPLE_TEST constant to point at the SimpleTest folder location before any of the toolset was loaded. This is no longer documented as it is now unnecessary for later versions. If you are using an earlier version you may need this constant. Consult the documentation that was bundled with the release that you are using or upgrade to Beta6 or later. No method SimpleBrowser::getCurrentUrl() -------------------------------------- This is replaced with the more versatile showRequest() for debugging. It only existed in this context for version Beta5. Later versions will have SimpleBrowser::getHistory() for tracking paths through pages. It is renamed as getUrl() since 1.0RC1. No method Stub::setStubBaseClass() ---------------------------------- This method has finally been removed in 1.0RC1. Use SimpleTestOptions::setStubBaseClass() instead. No class CommandLineReporter ---------------------------- This was renamed to TextReporter in Beta3 and the deprecated version was removed in 1.0RC1. No method requireReturn() ------------------------- This was deprecated in Beta3 and is now removed. No method expectCookie() ------------------------ This method was abruptly removed in Beta4 so as to simplify the internals until another mechanism can replace it. As a workaround it is necessary to assert that the cookie has changed by setting it before the page fetch and then assert the desired value. No method clickSubmitByFormId() ------------------------------- This method had an incorrect name as no button was involved. It was renamed to submitByFormId() in Beta4 and the old version deprecated. Now removed. No method paintStart() or paintEnd() ------------------------------------ You should only get this error if you have subclassed the lower level reporting and test runner machinery. These methods have been broken down into events for test methods, events for test cases and events for group tests. The new methods are... paintStart() --> paintMethodStart(), paintCaseStart(), paintGroupStart() paintEnd() --> paintMethodEnd(), paintCaseEnd(), paintGroupEnd() This change was made in Beta3, ironically to make it easier to subclass the inner machinery. Simply duplicating the code you had in the previous methods should provide a temporary fix. No class TestDisplay -------------------- This has been folded into SimpleReporter in Beta3 and is now deprecated. It was removed in RC1. No method WebTestCase::fetch() ------------------------------ This was renamed get() in Alpha8. It is removed in Beta3. No method submit() ------------------ This has been renamed clickSubmit() in Beta1. The old method was removed in Beta2. No method clearHistory() ------------------------ This method is deprecated in Beta2 and removed in RC1. No method getCallCount() ------------------------ This method has been deprecated since Beta1 and has now been removed. There are now more ways to set expectations on counts and so this method should be unecessery. Removed in RC1. Cannot find file * ------------------ The following public name changes have occoured... simple_html_test.php --> reporter.php simple_mock.php --> mock_objects.php simple_unit.php --> unit_tester.php simple_web.php --> web_tester.php The old names were deprecated in Alpha8 and removed in Beta1. No method attachObserver() -------------------------- Prior to the Alpha8 release the old internal observer pattern was gutted and replaced with a visitor. This is to trade flexibility of test case expansion against the ease of writing user interfaces. Code such as... $test = &new MyTestCase(); $test->attachObserver(new TestHtmlDisplay()); $test->run(); ...should be rewritten as... $test = &new MyTestCase(); $test->run(new HtmlReporter()); If you previously attached multiple observers then the workaround is to run the tests twice, once with each, until they can be combined. For one observer the old method is simulated in Alpha 8, but is removed in Beta1. No class TestHtmlDisplay ------------------------ This class has been renamed to HtmlReporter in Alpha8. It is supported, but deprecated in Beta1 and removed in Beta2. If you have subclassed the display for your own design, then you will have to extend this class (HtmlReporter) instead. If you have accessed the event queue by overriding the notify() method then I am afraid you are in big trouble :(. The reporter is now carried around the test suite by the runner classes and the methods called directly. In the unlikely event that this is a problem and you don't want to upgrade the test tool then simplest is to write your own runner class and invoke the tests with... $test->accept(new MyRunner(new MyReporter())); ...rather than the run method. This should be easier to extend anyway and gives much more control. Even this method is overhauled in Beta3 where the runner class can be set within the test case. Really the best thing to do is to upgrade to this version as whatever you were trying to achieve before should now be very much easier. Missing set options method -------------------------- All test suite options are now in one class called SimpleTestOptions. This means that options are set differently... GroupTest::ignore() --> SimpleTestOptions::ignore() Mock::setMockBaseClass() --> SimpleTestOptions::setMockBaseClass() These changed in Alpha8 and the old versions are now removed in RC1. No method setExpected*() ------------------------ The mock expectations changed their names in Alpha4 and the old names ceased to be supported in Alpha8. The changes are... setExpectedArguments() --> expectArguments() setExpectedArgumentsSequence() --> expectArgumentsAt() setExpectedCallCount() --> expectCallCount() setMaximumCallCount() --> expectMaximumCallCount() The parameters remained the same. Swift-4.2.1/test-suite/lib/simpletest/LICENSE100644 0 0 63471 12000050366 16036 0ustar 0 0 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! Swift-4.2.1/test-suite/lib/simpletest/README100644 0 0 10726 12000050366 15704 0ustar 0 0 SimpleTest ========== You probably got this package from... http://simpletest.sourceforge.net/projects/simpletest/ If there is no licence agreement with this package please download a version from the location above. You must read and accept that licence to use this software. The file is titled simply LICENSE. What is it? It's a framework for unit testing, web site testing and mock objects for PHP 5.0.5+. If you have used JUnit, you will find this PHP unit testing version very similar. Also included is a mock objects and server stubs generator. The stubs can have return values set for different arguments, can have sequences set also by arguments and can return items by reference. The mocks inherit all of this functionality and can also have expectations set, again in sequences and for different arguments. A web tester similar in concept to JWebUnit is also included. There is no JavaScript or tables support, but forms, authentication, cookies and frames are handled. You can see a release schedule at http://simpletest.org/en/overview.html which is also copied to the documentation folder with this release. A full PHPDocumenter API documentation exists at http://simpletest.org/api/. The user interface is minimal in the extreme, but a lot of information flows from the test suite. After version 1.0 we will release a better web UI, but we are leaving XUL and GTk versions to volunteers as everybody has their own opinion on a good GUI, and we don't want to discourage development by shipping one with the toolkit. You can download an Eclipse plug-in separately. You are looking at a second full release. The unit tests for SimpleTest itself can be run here... simpletest/test/unit_tests.php And tests involving live network connections as well are here... simpletest/test/all_tests.php The full tests will typically overrun the 8Mb limit often allowed to a PHP process. A workaround is to run the tests on the command with a custom php.ini file if you do not have access to your server version. You will have to edit the all_tests.php file if you are accesssing the internet through a proxy server. See the comments in all_tests.php for instructions. The full tests read some test data from the LastCraft site. If the site is down or has been modified for a later version then you will get spurious errors. A unit_tests.php failure on the other hand would be very serious. As far as we know we haven't yet managed to check in any unit test failures, so please correct us if you find one. Even if all of the tests run please verify that your existing test suites also function as expected. If they don't see the file... HELP_MY_TESTS_DONT_WORK_ANYMORE This contains information on interface changes. It also points out deprecated interfaces, so you should read this even if all of your current tests appear to run. There is a documentation folder which contains the core reference information in English and French, although this information is fairly basic. You can find a tutorial on... http://simpletest.org/en/first_test_tutorial.html ...to get you started and this material will eventually become included with the project documentation. A French translation exists at... http://simpletest.org/fr/first_test_tutorial.html If you download and use, and possibly even extend this tool, please let us know. Any feedback, even bad, is always welcome and we will work to get your suggestions into the next release. Ideally please send your comments to... simpletest-support@lists.sourceforge.net ...so that others can read them too. We usually try to respond within 48 hours. There is no change log except at Sourceforge. You can visit the release notes to see the completed TODO list after each cycle and also the status of any bugs, but if the bug is recent then it will be fixed in SVN only. The SVN check-ins always have all the tests passing and so SVN snapshots should be pretty usable, although the code may not look so good internally. Oh, yes. It is called "Simple" because it should be simple to use. We intend to add a complete set of tools for a test first and "test as you code" type of development. "Simple" does not mean "Lite" in this context. Thanks to everyone who has sent comments and offered suggestions. They really are invaluable, but sadly you are too many to mention in full. Thanks to all on the advanced PHP forum on SitePoint, especially Harry Fuecks. Early adopters are always an inspiration. Marcus Baker, Jason Sweat, Travis Swicegood, Perrick Penet and Edward Z. Yang. -- marcus@lastcraft.com Swift-4.2.1/test-suite/lib/simpletest/TODO.xml100644 0 0 17505 12000050366 16315 0ustar 0 0 TODO tasks for the current iteration

The following is the approximate plan for the next full point release.

Before each release we hope to have the following done. More may get done, depending on the interest of the volunteers, but this is the current minimum.

The aim of this release cycle is to produce a functionally identical version to the 1.0.1 release, but bug-fixed and fully compatible with PHP 5.0.5+ under E_STRICT. We are also hoping to flush out issues and use cases caused by people hacking against unpublished flex points in SimpleTest. We want to break people's code now, not while we are developing features down the line.

With the website move to a new server, and more developers, we are able and need to improve the test automation and developer cooperation. This release is a deep drawing of breath before going forward.

Undefined property $_reporter + fatal error The HELP_MY_TESTS_DONT_WORK_ANYMORE needs to be updated. README needs to be updated. Write XSLT code for this file so Perrick doesn't strangle me Ensure extensions are compatible with PHP5 constructor renaming in the current trunk. Update PEAR package task to be compatible with latest PEAR installer. PHP 5.3 compatible under E_STRICT PHP 5.2.0-5 compatible under E_STRICT PHP 5.1.0-6 compatible under E_STRICT continuous integration error_reporting(E_ALL|E_STRICT)gives lots of warning Remove all deprecated methods Drop underscores from protected methods and private variables. Make all variables private and add protected accessors where we use them internally. That way people will start complaining. Upon each complaint we'll add an accessor and capture the use case from them. We'll stick the use cases in the feature request tracker for now Move web site to new server Deprecate all mentions of GroupTest without breaking existing code. Need to swap the terminology for TestSuite in method names, etc. XmlReporter generating invalid XML Remove reflection facade for PHP4 label not assigned to radio and checkbox incorrect proxy requests Docblocks need to be cut back to a minimum PHP 5.0.5 compatible under E_STRICT Move acceptance tests sample pages to new server Remove reflection facade for PHP4 Throw away old tutorial PHP 6 compatible under E_STRICT Automated nightly test script that runs tests on all targeted PHP versions.
Current iteration is 1.1beta. Upcoming tasks for Unit tester, Reporter, Mock objects, Parser, Browser, Web tester, Documentation, Extensions and Build. Trackers for : feature requests, bugs and patches. software development, computer programmer, php programming, programming php, software development company, software development uk, php tutorial, bespoke software development uk, corporate web development, architecture, freelancer, php resources, wordtracker, web marketing, serach engines, web positioning, internet marketing
Swift-4.2.1/test-suite/lib/simpletest/VERSION100644 0 0 7 12000050366 15763 0ustar 0 0 1.1betaSwift-4.2.1/test-suite/lib/simpletest/authentication.php100644 0 0 16362 12000050366 20556 0ustar 0 0 type = $type; $this->root = $url->getBasePath(); $this->username = false; $this->password = false; } /** * Adds another location to the realm. * @param SimpleUrl $url Somewhere in realm. * @access public */ function stretch($url) { $this->root = $this->getCommonPath($this->root, $url->getPath()); } /** * Finds the common starting path. * @param string $first Path to compare. * @param string $second Path to compare. * @return string Common directories. * @access private */ protected function getCommonPath($first, $second) { $first = explode('/', $first); $second = explode('/', $second); for ($i = 0; $i < min(count($first), count($second)); $i++) { if ($first[$i] != $second[$i]) { return implode('/', array_slice($first, 0, $i)) . '/'; } } return implode('/', $first) . '/'; } /** * Sets the identity to try within this realm. * @param string $username Username in authentication dialog. * @param string $username Password in authentication dialog. * @access public */ function setIdentity($username, $password) { $this->username = $username; $this->password = $password; } /** * Accessor for current identity. * @return string Last succesful username. * @access public */ function getUsername() { return $this->username; } /** * Accessor for current identity. * @return string Last succesful password. * @access public */ function getPassword() { return $this->password; } /** * Test to see if the URL is within the directory * tree of the realm. * @param SimpleUrl $url URL to test. * @return boolean True if subpath. * @access public */ function isWithin($url) { if ($this->isIn($this->root, $url->getBasePath())) { return true; } if ($this->isIn($this->root, $url->getBasePath() . $url->getPage() . '/')) { return true; } return false; } /** * Tests to see if one string is a substring of * another. * @param string $part Small bit. * @param string $whole Big bit. * @return boolean True if the small bit is * in the big bit. * @access private */ protected function isIn($part, $whole) { return strpos($whole, $part) === 0; } } /** * Manages security realms. * @package SimpleTest * @subpackage WebTester */ class SimpleAuthenticator { private $realms; /** * Clears the realms. * @access public */ function SimpleAuthenticator() { $this->restartSession(); } /** * Starts with no realms set up. * @access public */ function restartSession() { $this->realms = array(); } /** * Adds a new realm centered the current URL. * Browsers privatey wildly on their behaviour in this * regard. Mozilla ignores the realm and presents * only when challenged, wasting bandwidth. IE * just carries on presenting until a new challenge * occours. SimpleTest tries to follow the spirit of * the original standards committee and treats the * base URL as the root of a file tree shaped realm. * @param SimpleUrl $url Base of realm. * @param string $type Authentication type for this * realm. Only Basic authentication * is currently supported. * @param string $realm Name of realm. * @access public */ function addRealm($url, $type, $realm) { $this->realms[$url->getHost()][$realm] = new SimpleRealm($type, $url); } /** * Sets the current identity to be presented * against that realm. * @param string $host Server hosting realm. * @param string $realm Name of realm. * @param string $username Username for realm. * @param string $password Password for realm. * @access public */ function setIdentityForRealm($host, $realm, $username, $password) { if (isset($this->realms[$host][$realm])) { $this->realms[$host][$realm]->setIdentity($username, $password); } } /** * Finds the name of the realm by comparing URLs. * @param SimpleUrl $url URL to test. * @return SimpleRealm Name of realm. * @access private */ protected function findRealmFromUrl($url) { if (! isset($this->realms[$url->getHost()])) { return false; } foreach ($this->realms[$url->getHost()] as $name => $realm) { if ($realm->isWithin($url)) { return $realm; } } return false; } /** * Presents the appropriate headers for this location. * @param SimpleHttpRequest $request Request to modify. * @param SimpleUrl $url Base of realm. * @access public */ function addHeaders(&$request, $url) { if ($url->getUsername() && $url->getPassword()) { $username = $url->getUsername(); $password = $url->getPassword(); } elseif ($realm = $this->findRealmFromUrl($url)) { $username = $realm->getUsername(); $password = $realm->getPassword(); } else { return; } $this->addBasicHeaders($request, $username, $password); } /** * Presents the appropriate headers for this * location for basic authentication. * @param SimpleHttpRequest $request Request to modify. * @param string $username Username for realm. * @param string $password Password for realm. * @access public */ static function addBasicHeaders(&$request, $username, $password) { if ($username && $password) { $request->addHeaderLine( 'Authorization: Basic ' . base64_encode("$username:$password")); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/autorun.php100644 0 0 6014 12000050366 17205 0ustar 0 0 createSuiteFromClasses( basename(initial_file()), $loader->selectRunnableTests($candidates)); $result = $suite->run(new DefaultReporter()); } catch (Exception $stack_frame_fix) { print $stack_frame_fix->getMessage(); $result = false; } if (SimpleReporter::inCli()) { exit($result ? 0 : 1); } } /** * Checks the current test context to see if a test has * ever been run. * @return boolean True if tests have run. */ function tests_have_run() { if ($context = SimpleTest::getContext()) { return (boolean)$context->getTest(); } return false; } /** * The first autorun file. * @return string Filename of first autorun script. */ function initial_file() { static $file = false; if (! $file) { if (isset($_SERVER, $_SERVER['SCRIPT_FILENAME'])) { $file = $_SERVER['SCRIPT_FILENAME']; } else { $included_files = get_included_files(); $file = reset($included_files); } } return $file; } /** * Just the classes from the first autorun script. May * get a few false positives, as it just does a regex based * on following the word "class". * @return array List of all possible classes in first * autorun script. */ function classes_defined_in_initial_file() { if (preg_match_all('/\bclass\s+(\w+)/i', file_get_contents(initial_file()), $matches)) { return array_map('strtolower', $matches[1]); } return array(); } /** * Every class since the first autorun include. This * is safe enough if require_once() is alwyas used. * @return array Class names. */ function capture_new_classes() { global $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES; return array_map('strtolower', array_diff(get_declared_classes(), $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES ? $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES : array())); } ?>Swift-4.2.1/test-suite/lib/simpletest/browser.php100644 0 0 106213 12000050366 17235 0ustar 0 0 sequence = array(); $this->position = -1; } /** * Test for no entries yet. * @return boolean True if empty. * @access private */ protected function isEmpty() { return ($this->position == -1); } /** * Test for being at the beginning. * @return boolean True if first. * @access private */ protected function atBeginning() { return ($this->position == 0) && ! $this->isEmpty(); } /** * Test for being at the last entry. * @return boolean True if last. * @access private */ protected function atEnd() { return ($this->position + 1 >= count($this->sequence)) && ! $this->isEmpty(); } /** * Adds a successfully fetched page to the history. * @param SimpleUrl $url URL of fetch. * @param SimpleEncoding $parameters Any post data with the fetch. * @access public */ function recordEntry($url, $parameters) { $this->dropFuture(); array_push( $this->sequence, array('url' => $url, 'parameters' => $parameters)); $this->position++; } /** * Last fully qualified URL for current history * position. * @return SimpleUrl URL for this position. * @access public */ function getUrl() { if ($this->isEmpty()) { return false; } return $this->sequence[$this->position]['url']; } /** * Parameters of last fetch from current history * position. * @return SimpleFormEncoding Post parameters. * @access public */ function getParameters() { if ($this->isEmpty()) { return false; } return $this->sequence[$this->position]['parameters']; } /** * Step back one place in the history. Stops at * the first page. * @return boolean True if any previous entries. * @access public */ function back() { if ($this->isEmpty() || $this->atBeginning()) { return false; } $this->position--; return true; } /** * Step forward one place. If already at the * latest entry then nothing will happen. * @return boolean True if any future entries. * @access public */ function forward() { if ($this->isEmpty() || $this->atEnd()) { return false; } $this->position++; return true; } /** * Ditches all future entries beyond the current * point. * @access private */ protected function dropFuture() { if ($this->isEmpty()) { return; } while (! $this->atEnd()) { array_pop($this->sequence); } } } /** * Simulated web browser. This is an aggregate of * the user agent, the HTML parsing, request history * and the last header set. * @package SimpleTest * @subpackage WebTester */ class SimpleBrowser { private $user_agent; private $page; private $history; private $ignore_frames; private $maximum_nested_frames; /** * Starts with a fresh browser with no * cookie or any other state information. The * exception is that a default proxy will be * set up if specified in the options. * @access public */ function __construct() { $this->user_agent = $this->createUserAgent(); $this->user_agent->useProxy( SimpleTest::getDefaultProxy(), SimpleTest::getDefaultProxyUsername(), SimpleTest::getDefaultProxyPassword()); $this->page = new SimplePage(); $this->history = $this->createHistory(); $this->ignore_frames = false; $this->maximum_nested_frames = DEFAULT_MAX_NESTED_FRAMES; } /** * Creates the underlying user agent. * @return SimpleFetcher Content fetcher. * @access protected */ protected function createUserAgent() { return new SimpleUserAgent(); } /** * Creates a new empty history list. * @return SimpleBrowserHistory New list. * @access protected */ protected function createHistory() { return new SimpleBrowserHistory(); } /** * Disables frames support. Frames will not be fetched * and the frameset page will be used instead. * @access public */ function ignoreFrames() { $this->ignore_frames = true; } /** * Enables frames support. Frames will be fetched from * now on. * @access public */ function useFrames() { $this->ignore_frames = false; } /** * Switches off cookie sending and recieving. * @access public */ function ignoreCookies() { $this->user_agent->ignoreCookies(); } /** * Switches back on the cookie sending and recieving. * @access public */ function useCookies() { $this->user_agent->useCookies(); } /** * Parses the raw content into a page. Will load further * frame pages unless frames are disabled. * @param SimpleHttpResponse $response Response from fetch. * @param integer $depth Nested frameset depth. * @return SimplePage Parsed HTML. * @access private */ protected function parse($response, $depth = 0) { $page = $this->buildPage($response); if ($this->ignore_frames || ! $page->hasFrames() || ($depth > $this->maximum_nested_frames)) { return $page; } $frameset = new SimpleFrameset($page); foreach ($page->getFrameset() as $key => $url) { $frame = $this->fetch($url, new SimpleGetEncoding(), $depth + 1); $frameset->addFrame($frame, $key); } return $frameset; } /** * Assembles the parsing machinery and actually parses * a single page. Frees all of the builder memory and so * unjams the PHP memory management. * @param SimpleHttpResponse $response Response from fetch. * @return SimplePage Parsed top level page. * @access protected */ protected function buildPage($response) { $builder = new SimplePageBuilder(); $page = $builder->parse($response); $builder->free(); unset($builder); return $page; } /** * Fetches a page. Jointly recursive with the parse() * method as it descends a frameset. * @param string/SimpleUrl $url Target to fetch. * @param SimpleEncoding $encoding GET/POST parameters. * @param integer $depth Nested frameset depth protection. * @return SimplePage Parsed page. * @access private */ protected function fetch($url, $encoding, $depth = 0) { $response = $this->user_agent->fetchResponse($url, $encoding); if ($response->isError()) { return new SimplePage($response); } return $this->parse($response, $depth); } /** * Fetches a page or a single frame if that is the current * focus. * @param SimpleUrl $url Target to fetch. * @param SimpleEncoding $parameters GET/POST parameters. * @return string Raw content of page. * @access private */ protected function load($url, $parameters) { $frame = $url->getTarget(); if (! $frame || ! $this->page->hasFrames() || (strtolower($frame) == '_top')) { return $this->loadPage($url, $parameters); } return $this->loadFrame(array($frame), $url, $parameters); } /** * Fetches a page and makes it the current page/frame. * @param string/SimpleUrl $url Target to fetch as string. * @param SimplePostEncoding $parameters POST parameters. * @return string Raw content of page. * @access private */ protected function loadPage($url, $parameters) { $this->page = $this->fetch($url, $parameters); $this->history->recordEntry( $this->page->getUrl(), $this->page->getRequestData()); return $this->page->getRaw(); } /** * Fetches a frame into the existing frameset replacing the * original. * @param array $frames List of names to drill down. * @param string/SimpleUrl $url Target to fetch as string. * @param SimpleFormEncoding $parameters POST parameters. * @return string Raw content of page. * @access private */ protected function loadFrame($frames, $url, $parameters) { $page = $this->fetch($url, $parameters); $this->page->setFrame($frames, $page); return $page->getRaw(); } /** * Removes expired and temporary cookies as if * the browser was closed and re-opened. * @param string/integer $date Time when session restarted. * If omitted then all persistent * cookies are kept. * @access public */ function restart($date = false) { $this->user_agent->restart($date); } /** * Adds a header to every fetch. * @param string $header Header line to add to every * request until cleared. * @access public */ function addHeader($header) { $this->user_agent->addHeader($header); } /** * Ages the cookies by the specified time. * @param integer $interval Amount in seconds. * @access public */ function ageCookies($interval) { $this->user_agent->ageCookies($interval); } /** * Sets an additional cookie. If a cookie has * the same name and path it is replaced. * @param string $name Cookie key. * @param string $value Value of cookie. * @param string $host Host upon which the cookie is valid. * @param string $path Cookie path if not host wide. * @param string $expiry Expiry date. * @access public */ function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { $this->user_agent->setCookie($name, $value, $host, $path, $expiry); } /** * Reads the most specific cookie value from the * browser cookies. * @param string $host Host to search. * @param string $path Applicable path. * @param string $name Name of cookie to read. * @return string False if not present, else the * value as a string. * @access public */ function getCookieValue($host, $path, $name) { return $this->user_agent->getCookieValue($host, $path, $name); } /** * Reads the current cookies for the current URL. * @param string $name Key of cookie to find. * @return string Null if there is no current URL, false * if the cookie is not set. * @access public */ function getCurrentCookieValue($name) { return $this->user_agent->getBaseCookieValue($name, $this->page->getUrl()); } /** * Sets the maximum number of redirects before * a page will be loaded anyway. * @param integer $max Most hops allowed. * @access public */ function setMaximumRedirects($max) { $this->user_agent->setMaximumRedirects($max); } /** * Sets the maximum number of nesting of framed pages * within a framed page to prevent loops. * @param integer $max Highest depth allowed. * @access public */ function setMaximumNestedFrames($max) { $this->maximum_nested_frames = $max; } /** * Sets the socket timeout for opening a connection. * @param integer $timeout Maximum time in seconds. * @access public */ function setConnectionTimeout($timeout) { $this->user_agent->setConnectionTimeout($timeout); } /** * Sets proxy to use on all requests for when * testing from behind a firewall. Set URL * to false to disable. * @param string $proxy Proxy URL. * @param string $username Proxy username for authentication. * @param string $password Proxy password for authentication. * @access public */ function useProxy($proxy, $username = false, $password = false) { $this->user_agent->useProxy($proxy, $username, $password); } /** * Fetches the page content with a HEAD request. * Will affect cookies, but will not change the base URL. * @param string/SimpleUrl $url Target to fetch as string. * @param hash/SimpleHeadEncoding $parameters Additional parameters for * HEAD request. * @return boolean True if successful. * @access public */ function head($url, $parameters = false) { if (! is_object($url)) { $url = new SimpleUrl($url); } if ($this->getUrl()) { $url = $url->makeAbsolute($this->getUrl()); } $response = &$this->user_agent->fetchResponse($url, new SimpleHeadEncoding($parameters)); return ! $response->isError(); } /** * Fetches the page content with a simple GET request. * @param string/SimpleUrl $url Target to fetch. * @param hash/SimpleFormEncoding $parameters Additional parameters for * GET request. * @return string Content of page or false. * @access public */ function get($url, $parameters = false) { if (! is_object($url)) { $url = new SimpleUrl($url); } if ($this->getUrl()) { $url = $url->makeAbsolute($this->getUrl()); } return $this->load($url, new SimpleGetEncoding($parameters)); } /** * Fetches the page content with a POST request. * @param string/SimpleUrl $url Target to fetch as string. * @param hash/SimpleFormEncoding $parameters POST parameters. * @return string Content of page. * @access public */ function post($url, $parameters = false) { if (! is_object($url)) { $url = new SimpleUrl($url); } if ($this->getUrl()) { $url = $url->makeAbsolute($this->getUrl()); } return $this->load($url, new SimplePostEncoding($parameters)); } /** * Equivalent to hitting the retry button on the * browser. Will attempt to repeat the page fetch. If * there is no history to repeat it will give false. * @return string/boolean Content if fetch succeeded * else false. * @access public */ function retry() { $frames = $this->page->getFrameFocus(); if (count($frames) > 0) { $this->loadFrame( $frames, $this->page->getUrl(), $this->page->getRequestData()); return $this->page->getRaw(); } if ($url = $this->history->getUrl()) { $this->page = $this->fetch($url, $this->history->getParameters()); return $this->page->getRaw(); } return false; } /** * Equivalent to hitting the back button on the * browser. The browser history is unchanged on * failure. The page content is refetched as there * is no concept of content caching in SimpleTest. * @return boolean True if history entry and * fetch succeeded * @access public */ function back() { if (! $this->history->back()) { return false; } $content = $this->retry(); if (! $content) { $this->history->forward(); } return $content; } /** * Equivalent to hitting the forward button on the * browser. The browser history is unchanged on * failure. The page content is refetched as there * is no concept of content caching in SimpleTest. * @return boolean True if history entry and * fetch succeeded * @access public */ function forward() { if (! $this->history->forward()) { return false; } $content = $this->retry(); if (! $content) { $this->history->back(); } return $content; } /** * Retries a request after setting the authentication * for the current realm. * @param string $username Username for realm. * @param string $password Password for realm. * @return boolean True if successful fetch. Note * that authentication may still have * failed. * @access public */ function authenticate($username, $password) { if (! $this->page->getRealm()) { return false; } $url = $this->page->getUrl(); if (! $url) { return false; } $this->user_agent->setIdentity( $url->getHost(), $this->page->getRealm(), $username, $password); return $this->retry(); } /** * Accessor for a breakdown of the frameset. * @return array Hash tree of frames by name * or index if no name. * @access public */ function getFrames() { return $this->page->getFrames(); } /** * Accessor for current frame focus. Will be * false if no frame has focus. * @return integer/string/boolean Label if any, otherwise * the position in the frameset * or false if none. * @access public */ function getFrameFocus() { return $this->page->getFrameFocus(); } /** * Sets the focus by index. The integer index starts from 1. * @param integer $choice Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocusByIndex($choice) { return $this->page->setFrameFocusByIndex($choice); } /** * Sets the focus by name. * @param string $name Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocus($name) { return $this->page->setFrameFocus($name); } /** * Clears the frame focus. All frames will be searched * for content. * @access public */ function clearFrameFocus() { return $this->page->clearFrameFocus(); } /** * Accessor for last error. * @return string Error from last response. * @access public */ function getTransportError() { return $this->page->getTransportError(); } /** * Accessor for current MIME type. * @return string MIME type as string; e.g. 'text/html' * @access public */ function getMimeType() { return $this->page->getMimeType(); } /** * Accessor for last response code. * @return integer Last HTTP response code received. * @access public */ function getResponseCode() { return $this->page->getResponseCode(); } /** * Accessor for last Authentication type. Only valid * straight after a challenge (401). * @return string Description of challenge type. * @access public */ function getAuthentication() { return $this->page->getAuthentication(); } /** * Accessor for last Authentication realm. Only valid * straight after a challenge (401). * @return string Name of security realm. * @access public */ function getRealm() { return $this->page->getRealm(); } /** * Accessor for current URL of page or frame if * focused. * @return string Location of current page or frame as * a string. */ function getUrl() { $url = $this->page->getUrl(); return $url ? $url->asString() : false; } /** * Accessor for base URL of page if set via BASE tag * @return string base URL */ function getBaseUrl() { $url = $this->page->getBaseUrl(); return $url ? $url->asString() : false; } /** * Accessor for raw bytes sent down the wire. * @return string Original text sent. * @access public */ function getRequest() { return $this->page->getRequest(); } /** * Accessor for raw header information. * @return string Header block. * @access public */ function getHeaders() { return $this->page->getHeaders(); } /** * Accessor for raw page information. * @return string Original text content of web page. * @access public */ function getContent() { return $this->page->getRaw(); } /** * Accessor for plain text version of the page. * @return string Normalised text representation. * @access public */ function getContentAsText() { return $this->page->getText(); } /** * Accessor for parsed title. * @return string Title or false if no title is present. * @access public */ function getTitle() { return $this->page->getTitle(); } /** * Accessor for a list of all links in current page. * @return array List of urls with scheme of * http or https and hostname. * @access public */ function getUrls() { return $this->page->getUrls(); } /** * Sets all form fields with that name. * @param string $label Name or label of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setField($label, $value, $position=false) { return $this->page->setField(new SimpleByLabelOrName($label), $value, $position); } /** * Sets all form fields with that name. Will use label if * one is available (not yet implemented). * @param string $name Name of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setFieldByName($name, $value, $position=false) { return $this->page->setField(new SimpleByName($name), $value, $position); } /** * Sets all form fields with that id attribute. * @param string/integer $id Id of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setFieldById($id, $value) { return $this->page->setField(new SimpleById($id), $value); } /** * Accessor for a form element value within the page. * Finds the first match. * @param string $label Field label. * @return string/boolean A value if the field is * present, false if unchecked * and null if missing. * @access public */ function getField($label) { return $this->page->getField(new SimpleByLabelOrName($label)); } /** * Accessor for a form element value within the page. * Finds the first match. * @param string $name Field name. * @return string/boolean A string if the field is * present, false if unchecked * and null if missing. * @access public */ function getFieldByName($name) { return $this->page->getField(new SimpleByName($name)); } /** * Accessor for a form element value within the page. * @param string/integer $id Id of field in forms. * @return string/boolean A string if the field is * present, false if unchecked * and null if missing. * @access public */ function getFieldById($id) { return $this->page->getField(new SimpleById($id)); } /** * Clicks the submit button by label. The owning * form will be submitted by this. * @param string $label Button label. An unlabeled * button can be triggered by 'Submit'. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickSubmit($label = 'Submit', $additional = false) { if (! ($form = $this->page->getFormBySubmit(new SimpleByLabel($label)))) { return false; } $success = $this->load( $form->getAction(), $form->submitButton(new SimpleByLabel($label), $additional)); return ($success ? $this->getContent() : $success); } /** * Clicks the submit button by name attribute. The owning * form will be submitted by this. * @param string $name Button name. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickSubmitByName($name, $additional = false) { if (! ($form = $this->page->getFormBySubmit(new SimpleByName($name)))) { return false; } $success = $this->load( $form->getAction(), $form->submitButton(new SimpleByName($name), $additional)); return ($success ? $this->getContent() : $success); } /** * Clicks the submit button by ID attribute of the button * itself. The owning form will be submitted by this. * @param string $id Button ID. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickSubmitById($id, $additional = false) { if (! ($form = $this->page->getFormBySubmit(new SimpleById($id)))) { return false; } $success = $this->load( $form->getAction(), $form->submitButton(new SimpleById($id), $additional)); return ($success ? $this->getContent() : $success); } /** * Tests to see if a submit button exists with this * label. * @param string $label Button label. * @return boolean True if present. * @access public */ function isSubmit($label) { return (boolean)$this->page->getFormBySubmit(new SimpleByLabel($label)); } /** * Clicks the submit image by some kind of label. Usually * the alt tag or the nearest equivalent. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param string $label ID attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickImage($label, $x = 1, $y = 1, $additional = false) { if (! ($form = $this->page->getFormByImage(new SimpleByLabel($label)))) { return false; } $success = $this->load( $form->getAction(), $form->submitImage(new SimpleByLabel($label), $x, $y, $additional)); return ($success ? $this->getContent() : $success); } /** * Clicks the submit image by the name. Usually * the alt tag or the nearest equivalent. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param string $name Name attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickImageByName($name, $x = 1, $y = 1, $additional = false) { if (! ($form = $this->page->getFormByImage(new SimpleByName($name)))) { return false; } $success = $this->load( $form->getAction(), $form->submitImage(new SimpleByName($name), $x, $y, $additional)); return ($success ? $this->getContent() : $success); } /** * Clicks the submit image by ID attribute. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param integer/string $id ID attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form data. * @return string/boolean Page on success. * @access public */ function clickImageById($id, $x = 1, $y = 1, $additional = false) { if (! ($form = $this->page->getFormByImage(new SimpleById($id)))) { return false; } $success = $this->load( $form->getAction(), $form->submitImage(new SimpleById($id), $x, $y, $additional)); return ($success ? $this->getContent() : $success); } /** * Tests to see if an image exists with this * title or alt text. * @param string $label Image text. * @return boolean True if present. * @access public */ function isImage($label) { return (boolean)$this->page->getFormByImage(new SimpleByLabel($label)); } /** * Submits a form by the ID. * @param string $id The form ID. No submit button value * will be sent. * @return string/boolean Page on success. * @access public */ function submitFormById($id) { if (! ($form = $this->page->getFormById($id))) { return false; } $success = $this->load( $form->getAction(), $form->submit()); return ($success ? $this->getContent() : $success); } /** * Finds a URL by label. Will find the first link * found with this link text by default, or a later * one if an index is given. The match ignores case and * white space issues. * @param string $label Text between the anchor tags. * @param integer $index Link position counting from zero. * @return string/boolean URL on success. * @access public */ function getLink($label, $index = 0) { $urls = $this->page->getUrlsByLabel($label); if (count($urls) == 0) { return false; } if (count($urls) < $index + 1) { return false; } return $urls[$index]; } /** * Follows a link by label. Will click the first link * found with this link text by default, or a later * one if an index is given. The match ignores case and * white space issues. * @param string $label Text between the anchor tags. * @param integer $index Link position counting from zero. * @return string/boolean Page on success. * @access public */ function clickLink($label, $index = 0) { $url = $this->getLink($label, $index); if ($url === false) { return false; } $this->load($url, new SimpleGetEncoding()); return $this->getContent(); } /** * Finds a link by id attribute. * @param string $id ID attribute value. * @return string/boolean URL on success. * @access public */ function getLinkById($id) { return $this->page->getUrlById($id); } /** * Follows a link by id attribute. * @param string $id ID attribute value. * @return string/boolean Page on success. * @access public */ function clickLinkById($id) { if (! ($url = $this->getLinkById($id))) { return false; } $this->load($url, new SimpleGetEncoding()); return $this->getContent(); } /** * Clicks a visible text item. Will first try buttons, * then links and then images. * @param string $label Visible text or alt text. * @return string/boolean Raw page or false. * @access public */ function click($label) { $raw = $this->clickSubmit($label); if (! $raw) { $raw = $this->clickLink($label); } if (! $raw) { $raw = $this->clickImage($label); } return $raw; } /** * Tests to see if a click target exists. * @param string $label Visible text or alt text. * @return boolean True if target present. * @access public */ function isClickable($label) { return $this->isSubmit($label) || ($this->getLink($label) !== false) || $this->isImage($label); } } ?>Swift-4.2.1/test-suite/lib/simpletest/collector.php100644 0 0 7234 12000050366 17503 0ustar 0 0 * @package SimpleTest * @subpackage UnitTester * @version $Id: collector.php 1784 2008-04-26 13:07:14Z pp11 $ */ /** * The basic collector for {@link GroupTest} * * @see collect(), GroupTest::collect() * @package SimpleTest * @subpackage UnitTester */ class SimpleCollector { /** * Strips off any kind of slash at the end so as to normalise the path. * @param string $path Path to normalise. * @return string Path without trailing slash. */ protected function removeTrailingSlash($path) { if (substr($path, -1) == DIRECTORY_SEPARATOR) { return substr($path, 0, -1); } elseif (substr($path, -1) == '/') { return substr($path, 0, -1); } else { return $path; } } /** * Scans the directory and adds what it can. * @param object $test Group test with {@link GroupTest::addTestFile()} method. * @param string $path Directory to scan. * @see _attemptToAdd() */ function collect(&$test, $path) { $path = $this->removeTrailingSlash($path); if ($handle = opendir($path)) { while (($entry = readdir($handle)) !== false) { if ($this->isHidden($entry)) { continue; } $this->handle($test, $path . DIRECTORY_SEPARATOR . $entry); } closedir($handle); } } /** * This method determines what should be done with a given file and adds * it via {@link GroupTest::addTestFile()} if necessary. * * This method should be overriden to provide custom matching criteria, * such as pattern matching, recursive matching, etc. For an example, see * {@link SimplePatternCollector::_handle()}. * * @param object $test Group test with {@link GroupTest::addTestFile()} method. * @param string $filename A filename as generated by {@link collect()} * @see collect() * @access protected */ protected function handle(&$test, $file) { if (is_dir($file)) { return; } $test->addFile($file); } /** * Tests for hidden files so as to skip them. Currently * only tests for Unix hidden files. * @param string $filename Plain filename. * @return boolean True if hidden file. * @access private */ protected function isHidden($filename) { return strncmp($filename, '.', 1) == 0; } } /** * An extension to {@link SimpleCollector} that only adds files matching a * given pattern. * * @package SimpleTest * @subpackage UnitTester * @see SimpleCollector */ class SimplePatternCollector extends SimpleCollector { private $pattern; /** * * @param string $pattern Perl compatible regex to test name against * See {@link http://us4.php.net/manual/en/reference.pcre.pattern.syntax.php PHP's PCRE} * for full documentation of valid pattern.s */ function __construct($pattern = '/php$/i') { $this->pattern = $pattern; } /** * Attempts to add files that match a given pattern. * * @see SimpleCollector::_handle() * @param object $test Group test with {@link GroupTest::addTestFile()} method. * @param string $path Directory to scan. * @access protected */ protected function handle(&$test, $filename) { if (preg_match($this->pattern, $filename)) { parent::handle($test, $filename); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/compatibility.php100644 0 0 12426 12000050366 20405 0ustar 0 0 = 0) { eval('$copy = clone $object;'); return $copy; } return $object; } /** * Identity test. Drops back to equality + types for PHP5 * objects as the === operator counts as the * stronger reference constraint. * @param mixed $first Test subject. * @param mixed $second Comparison object. * @return boolean True if identical. * @access public */ static function isIdentical($first, $second) { if (version_compare(phpversion(), '5') >= 0) { return SimpleTestCompatibility::isIdenticalType($first, $second); } if ($first != $second) { return false; } return ($first === $second); } /** * Recursive type test. * @param mixed $first Test subject. * @param mixed $second Comparison object. * @return boolean True if same type. * @access private */ protected static function isIdenticalType($first, $second) { if (gettype($first) != gettype($second)) { return false; } if (is_object($first) && is_object($second)) { if (get_class($first) != get_class($second)) { return false; } return SimpleTestCompatibility::isArrayOfIdenticalTypes( get_object_vars($first), get_object_vars($second)); } if (is_array($first) && is_array($second)) { return SimpleTestCompatibility::isArrayOfIdenticalTypes($first, $second); } if ($first !== $second) { return false; } return true; } /** * Recursive type test for each element of an array. * @param mixed $first Test subject. * @param mixed $second Comparison object. * @return boolean True if identical. * @access private */ protected static function isArrayOfIdenticalTypes($first, $second) { if (array_keys($first) != array_keys($second)) { return false; } foreach (array_keys($first) as $key) { $is_identical = SimpleTestCompatibility::isIdenticalType( $first[$key], $second[$key]); if (! $is_identical) { return false; } } return true; } /** * Test for two variables being aliases. * @param mixed $first Test subject. * @param mixed $second Comparison object. * @return boolean True if same. * @access public */ static function isReference(&$first, &$second) { if (version_compare(phpversion(), '5', '>=') && is_object($first)) { return ($first === $second); } if (is_object($first) && is_object($second)) { $id = uniqid("test"); $first->$id = true; $is_ref = isset($second->$id); unset($first->$id); return $is_ref; } $temp = $first; $first = uniqid("test"); $is_ref = ($first === $second); $first = $temp; return $is_ref; } /** * Test to see if an object is a member of a * class hiearchy. * @param object $object Object to test. * @param string $class Root name of hiearchy. * @return boolean True if class in hiearchy. * @access public */ static function isA($object, $class) { if (version_compare(phpversion(), '5') >= 0) { if (! class_exists($class, false)) { if (function_exists('interface_exists')) { if (! interface_exists($class, false)) { return false; } } } eval("\$is_a = \$object instanceof $class;"); return $is_a; } if (function_exists('is_a')) { return is_a($object, $class); } return ((strtolower($class) == get_class($object)) or (is_subclass_of($object, $class))); } /** * Sets a socket timeout for each chunk. * @param resource $handle Socket handle. * @param integer $timeout Limit in seconds. * @access public */ static function setTimeout($handle, $timeout) { if (function_exists('stream_set_timeout')) { stream_set_timeout($handle, $timeout, 0); } elseif (function_exists('socket_set_timeout')) { socket_set_timeout($handle, $timeout, 0); } elseif (function_exists('set_socket_timeout')) { set_socket_timeout($handle, $timeout, 0); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/cookies.php100644 0 0 27063 12000050366 17173 0ustar 0 0 host = false; $this->name = $name; $this->value = $value; $this->path = ($path ? $this->fixPath($path) : "/"); $this->expiry = false; if (is_string($expiry)) { $this->expiry = strtotime($expiry); } elseif (is_integer($expiry)) { $this->expiry = $expiry; } $this->is_secure = $is_secure; } /** * Sets the host. The cookie rules determine * that the first two parts are taken for * certain TLDs and three for others. If the * new host does not match these rules then the * call will fail. * @param string $host New hostname. * @return boolean True if hostname is valid. * @access public */ function setHost($host) { if ($host = $this->truncateHost($host)) { $this->host = $host; return true; } return false; } /** * Accessor for the truncated host to which this * cookie applies. * @return string Truncated hostname. * @access public */ function getHost() { return $this->host; } /** * Test for a cookie being valid for a host name. * @param string $host Host to test against. * @return boolean True if the cookie would be valid * here. */ function isValidHost($host) { return ($this->truncateHost($host) === $this->getHost()); } /** * Extracts just the domain part that determines a * cookie's host validity. * @param string $host Host name to truncate. * @return string Domain or false on a bad host. * @access private */ protected function truncateHost($host) { $tlds = SimpleUrl::getAllTopLevelDomains(); if (preg_match('/[a-z\-]+\.(' . $tlds . ')$/i', $host, $matches)) { return $matches[0]; } elseif (preg_match('/[a-z\-]+\.[a-z\-]+\.[a-z\-]+$/i', $host, $matches)) { return $matches[0]; } return false; } /** * Accessor for name. * @return string Cookie key. * @access public */ function getName() { return $this->name; } /** * Accessor for value. A deleted cookie will * have an empty string for this. * @return string Cookie value. * @access public */ function getValue() { return $this->value; } /** * Accessor for path. * @return string Valid cookie path. * @access public */ function getPath() { return $this->path; } /** * Tests a path to see if the cookie applies * there. The test path must be longer or * equal to the cookie path. * @param string $path Path to test against. * @return boolean True if cookie valid here. * @access public */ function isValidPath($path) { return (strncmp( $this->fixPath($path), $this->getPath(), strlen($this->getPath())) == 0); } /** * Accessor for expiry. * @return string Expiry string. * @access public */ function getExpiry() { if (! $this->expiry) { return false; } return gmdate("D, d M Y H:i:s", $this->expiry) . " GMT"; } /** * Test to see if cookie is expired against * the cookie format time or timestamp. * Will give true for a session cookie. * @param integer/string $now Time to test against. Result * will be false if this time * is later than the cookie expiry. * Can be either a timestamp integer * or a cookie format date. * @access public */ function isExpired($now) { if (! $this->expiry) { return true; } if (is_string($now)) { $now = strtotime($now); } return ($this->expiry < $now); } /** * Ages the cookie by the specified number of * seconds. * @param integer $interval In seconds. * @public */ function agePrematurely($interval) { if ($this->expiry) { $this->expiry -= $interval; } } /** * Accessor for the secure flag. * @return boolean True if cookie needs SSL. * @access public */ function isSecure() { return $this->is_secure; } /** * Adds a trailing and leading slash to the path * if missing. * @param string $path Path to fix. * @access private */ protected function fixPath($path) { if (substr($path, 0, 1) != '/') { $path = '/' . $path; } if (substr($path, -1, 1) != '/') { $path .= '/'; } return $path; } } /** * Repository for cookies. This stuff is a * tiny bit browser dependent. * @package SimpleTest * @subpackage WebTester */ class SimpleCookieJar { private $cookies; /** * Constructor. Jar starts empty. * @access public */ function __construct() { $this->cookies = array(); } /** * Removes expired and temporary cookies as if * the browser was closed and re-opened. * @param string/integer $now Time to test expiry against. * @access public */ function restartSession($date = false) { $surviving_cookies = array(); for ($i = 0; $i < count($this->cookies); $i++) { if (! $this->cookies[$i]->getValue()) { continue; } if (! $this->cookies[$i]->getExpiry()) { continue; } if ($date && $this->cookies[$i]->isExpired($date)) { continue; } $surviving_cookies[] = $this->cookies[$i]; } $this->cookies = $surviving_cookies; } /** * Ages all cookies in the cookie jar. * @param integer $interval The old session is moved * into the past by this number * of seconds. Cookies now over * age will be removed. * @access public */ function agePrematurely($interval) { for ($i = 0; $i < count($this->cookies); $i++) { $this->cookies[$i]->agePrematurely($interval); } } /** * Sets an additional cookie. If a cookie has * the same name and path it is replaced. * @param string $name Cookie key. * @param string $value Value of cookie. * @param string $host Host upon which the cookie is valid. * @param string $path Cookie path if not host wide. * @param string $expiry Expiry date. * @access public */ function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { $cookie = new SimpleCookie($name, $value, $path, $expiry); if ($host) { $cookie->setHost($host); } $this->cookies[$this->findFirstMatch($cookie)] = $cookie; } /** * Finds a matching cookie to write over or the * first empty slot if none. * @param SimpleCookie $cookie Cookie to write into jar. * @return integer Available slot. * @access private */ protected function findFirstMatch($cookie) { for ($i = 0; $i < count($this->cookies); $i++) { $is_match = $this->isMatch( $cookie, $this->cookies[$i]->getHost(), $this->cookies[$i]->getPath(), $this->cookies[$i]->getName()); if ($is_match) { return $i; } } return count($this->cookies); } /** * Reads the most specific cookie value from the * browser cookies. Looks for the longest path that * matches. * @param string $host Host to search. * @param string $path Applicable path. * @param string $name Name of cookie to read. * @return string False if not present, else the * value as a string. * @access public */ function getCookieValue($host, $path, $name) { $longest_path = ''; foreach ($this->cookies as $cookie) { if ($this->isMatch($cookie, $host, $path, $name)) { if (strlen($cookie->getPath()) > strlen($longest_path)) { $value = $cookie->getValue(); $longest_path = $cookie->getPath(); } } } return (isset($value) ? $value : false); } /** * Tests cookie for matching against search * criteria. * @param SimpleTest $cookie Cookie to test. * @param string $host Host must match. * @param string $path Cookie path must be shorter than * this path. * @param string $name Name must match. * @return boolean True if matched. * @access private */ protected function isMatch($cookie, $host, $path, $name) { if ($cookie->getName() != $name) { return false; } if ($host && $cookie->getHost() && ! $cookie->isValidHost($host)) { return false; } if (! $cookie->isValidPath($path)) { return false; } return true; } /** * Uses a URL to sift relevant cookies by host and * path. Results are list of strings of form "name=value". * @param SimpleUrl $url Url to select by. * @return array Valid name and value pairs. * @access public */ function selectAsPairs($url) { $pairs = array(); foreach ($this->cookies as $cookie) { if ($this->isMatch($cookie, $url->getHost(), $url->getPath(), $cookie->getName())) { $pairs[] = $cookie->getName() . '=' . $cookie->getValue(); } } return $pairs; } } ?>Swift-4.2.1/test-suite/lib/simpletest/default_reporter.php100644 0 0 11573 12000050366 21104 0ustar 0 0 'case', 'c' => 'case', 'test' => 'test', 't' => 'test', ); private $case = ''; private $test = ''; private $xml = false; private $help = false; private $no_skips = false; /** * Parses raw command line arguments into object properties. * @param string $arguments Raw commend line arguments. */ function __construct($arguments) { if (! is_array($arguments)) { return; } foreach ($arguments as $i => $argument) { if (preg_match('/^--?(test|case|t|c)=(.+)$/', $argument, $matches)) { $property = $this->to_property[$matches[1]]; $this->$property = $matches[2]; } elseif (preg_match('/^--?(test|case|t|c)$/', $argument, $matches)) { $property = $this->to_property[$matches[1]]; if (isset($arguments[$i + 1])) { $this->$property = $arguments[$i + 1]; } } elseif (preg_match('/^--?(xml|x)$/', $argument)) { $this->xml = true; } elseif (preg_match('/^--?(no-skip|no-skips|s)$/', $argument)) { $this->no_skips = true; } elseif (preg_match('/^--?(help|h)$/', $argument)) { $this->help = true; } } } /** * Run only this test. * @return string Test name to run. */ function getTest() { return $this->test; } /** * Run only this test suite. * @return string Test class name to run. */ function getTestCase() { return $this->case; } /** * Output should be XML or not. * @return boolean True if XML desired. */ function isXml() { return $this->xml; } /** * Output should suppress skip messages. * @return boolean True for no skips. */ function noSkips() { return $this->no_skips; } /** * Output should be a help message. Disabled during XML mode. * @return boolean True if help message desired. */ function help() { return $this->help && !$this->xml; } /** * Returns plain-text help message for command line runner. * @return string String help message */ function getHelpText() { return << [args...] -c Run only the test-case -t Run only the test method -s Suppress skip messages -x Return test results in XML -h Display this help message HELP; } } /** * The default reporter used by SimpleTest's autorun * feature. The actual reporters used are dependency * injected and can be overridden. * @package SimpleTest * @subpackage UnitTester */ class DefaultReporter extends SimpleReporterDecorator { /** * Assembles the appopriate reporter for the environment. */ function __construct() { if (SimpleReporter::inCli()) { $parser = new SimpleCommandLineParser($_SERVER['argv']); $interfaces = $parser->isXml() ? array('XmlReporter') : array('TextReporter'); if ($parser->help()) { // I'm not sure if we should do the echo'ing here -- ezyang echo $parser->getHelpText(); exit(1); } $reporter = new SelectiveReporter( SimpleTest::preferred($interfaces), $parser->getTestCase(), $parser->getTest()); if ($parser->noSkips()) { $reporter = new NoSkipsReporter($reporter); } } else { $reporter = new SelectiveReporter( SimpleTest::preferred('HtmlReporter'), @$_GET['c'], @$_GET['t']); if (@$_GET['skips'] == 'no' || @$_GET['show-skips'] == 'no') { $reporter = new NoSkipsReporter($reporter); } } parent::__construct($reporter); } } ?>Swift-4.2.1/test-suite/lib/simpletest/detached.php100644 0 0 5471 12000050366 17257 0ustar 0 0 command = $command; $this->dry_command = $dry_command ? $dry_command : $command; $this->size = false; } /** * Accessor for the test name for subclasses. * @return string Name of the test. * @access public */ function getLabel() { return $this->command; } /** * Runs the top level test for this class. Currently * reads the data as a single chunk. I'll fix this * once I have added iteration to the browser. * @param SimpleReporter $reporter Target of test results. * @returns boolean True if no failures. * @access public */ function run(&$reporter) { $shell = &new SimpleShell(); $shell->execute($this->command); $parser = &$this->createParser($reporter); if (! $parser->parse($shell->getOutput())) { trigger_error('Cannot parse incoming XML from [' . $this->command . ']'); return false; } return true; } /** * Accessor for the number of subtests. * @return integer Number of test cases. * @access public */ function getSize() { if ($this->size === false) { $shell = &new SimpleShell(); $shell->execute($this->dry_command); $reporter = &new SimpleReporter(); $parser = &$this->createParser($reporter); if (! $parser->parse($shell->getOutput())) { trigger_error('Cannot parse incoming XML from [' . $this->dry_command . ']'); return false; } $this->size = $reporter->getTestCaseCount(); } return $this->size; } /** * Creates the XML parser. * @param SimpleReporter $reporter Target of test results. * @return SimpleTestXmlListener XML reader. * @access protected */ protected function &createParser(&$reporter) { return new SimpleTestXmlParser($reporter); } } ?>Swift-4.2.1/test-suite/lib/simpletest/dumper.php100644 0 0 32036 12000050366 17027 0ustar 0 0 getType($value); switch($type) { case "Null": return "NULL"; case "Boolean": return "Boolean: " . ($value ? "true" : "false"); case "Array": return "Array: " . count($value) . " items"; case "Object": return "Object: of " . get_class($value); case "String": return "String: " . $this->clipString($value, 200); default: return "$type: $value"; } return "Unknown"; } /** * Gets the string representation of a type. * @param mixed $value Variable to check against. * @return string Type. * @access public */ function getType($value) { if (! isset($value)) { return "Null"; } elseif (is_bool($value)) { return "Boolean"; } elseif (is_string($value)) { return "String"; } elseif (is_integer($value)) { return "Integer"; } elseif (is_float($value)) { return "Float"; } elseif (is_array($value)) { return "Array"; } elseif (is_resource($value)) { return "Resource"; } elseif (is_object($value)) { return "Object"; } return "Unknown"; } /** * Creates a human readable description of the * difference between two variables. Uses a * dynamic call. * @param mixed $first First variable. * @param mixed $second Value to compare with. * @param boolean $identical If true then type anomolies count. * @return string Description of difference. * @access public */ function describeDifference($first, $second, $identical = false) { if ($identical) { if (! $this->isTypeMatch($first, $second)) { return "with type mismatch as [" . $this->describeValue($first) . "] does not match [" . $this->describeValue($second) . "]"; } } $type = $this->getType($first); if ($type == "Unknown") { return "with unknown type"; } $method = 'describe' . $type . 'Difference'; return $this->$method($first, $second, $identical); } /** * Tests to see if types match. * @param mixed $first First variable. * @param mixed $second Value to compare with. * @return boolean True if matches. * @access private */ protected function isTypeMatch($first, $second) { return ($this->getType($first) == $this->getType($second)); } /** * Clips a string to a maximum length. * @param string $value String to truncate. * @param integer $size Minimum string size to show. * @param integer $position Centre of string section. * @return string Shortened version. * @access public */ function clipString($value, $size, $position = 0) { $length = strlen($value); if ($length <= $size) { return $value; } $position = min($position, $length); $start = ($size/2 > $position ? 0 : $position - $size/2); if ($start + $size > $length) { $start = $length - $size; } $value = substr($value, $start, $size); return ($start > 0 ? "..." : "") . $value . ($start + $size < $length ? "..." : ""); } /** * Creates a human readable description of the * difference between two variables. The minimal * version. * @param null $first First value. * @param mixed $second Value to compare with. * @return string Human readable description. * @access private */ protected function describeGenericDifference($first, $second) { return "as [" . $this->describeValue($first) . "] does not match [" . $this->describeValue($second) . "]"; } /** * Creates a human readable description of the * difference between a null and another variable. * @param null $first First null. * @param mixed $second Null to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeNullDifference($first, $second, $identical) { return $this->describeGenericDifference($first, $second); } /** * Creates a human readable description of the * difference between a boolean and another variable. * @param boolean $first First boolean. * @param mixed $second Boolean to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeBooleanDifference($first, $second, $identical) { return $this->describeGenericDifference($first, $second); } /** * Creates a human readable description of the * difference between a string and another variable. * @param string $first First string. * @param mixed $second String to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeStringDifference($first, $second, $identical) { if (is_object($second) || is_array($second)) { return $this->describeGenericDifference($first, $second); } $position = $this->stringDiffersAt($first, $second); $message = "at character $position"; $message .= " with [" . $this->clipString($first, 200, $position) . "] and [" . $this->clipString($second, 200, $position) . "]"; return $message; } /** * Creates a human readable description of the * difference between an integer and another variable. * @param integer $first First number. * @param mixed $second Number to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeIntegerDifference($first, $second, $identical) { if (is_object($second) || is_array($second)) { return $this->describeGenericDifference($first, $second); } return "because [" . $this->describeValue($first) . "] differs from [" . $this->describeValue($second) . "] by " . abs($first - $second); } /** * Creates a human readable description of the * difference between two floating point numbers. * @param float $first First float. * @param mixed $second Float to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeFloatDifference($first, $second, $identical) { if (is_object($second) || is_array($second)) { return $this->describeGenericDifference($first, $second); } return "because [" . $this->describeValue($first) . "] differs from [" . $this->describeValue($second) . "] by " . abs($first - $second); } /** * Creates a human readable description of the * difference between two arrays. * @param array $first First array. * @param mixed $second Array to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeArrayDifference($first, $second, $identical) { if (! is_array($second)) { return $this->describeGenericDifference($first, $second); } if (! $this->isMatchingKeys($first, $second, $identical)) { return "as key list [" . implode(", ", array_keys($first)) . "] does not match key list [" . implode(", ", array_keys($second)) . "]"; } foreach (array_keys($first) as $key) { if ($identical && ($first[$key] === $second[$key])) { continue; } if (! $identical && ($first[$key] == $second[$key])) { continue; } return "with member [$key] " . $this->describeDifference( $first[$key], $second[$key], $identical); } return ""; } /** * Compares two arrays to see if their key lists match. * For an identical match, the ordering and types of the keys * is significant. * @param array $first First array. * @param array $second Array to compare with. * @param boolean $identical If true then type anomolies count. * @return boolean True if matching. * @access private */ protected function isMatchingKeys($first, $second, $identical) { $first_keys = array_keys($first); $second_keys = array_keys($second); if ($identical) { return ($first_keys === $second_keys); } sort($first_keys); sort($second_keys); return ($first_keys == $second_keys); } /** * Creates a human readable description of the * difference between a resource and another variable. * @param resource $first First resource. * @param mixed $second Resource to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeResourceDifference($first, $second, $identical) { return $this->describeGenericDifference($first, $second); } /** * Creates a human readable description of the * difference between two objects. * @param object $first First object. * @param mixed $second Object to compare with. * @param boolean $identical If true then type anomolies count. * @return string Human readable description. * @access private */ protected function describeObjectDifference($first, $second, $identical) { if (! is_object($second)) { return $this->describeGenericDifference($first, $second); } return $this->describeArrayDifference( get_object_vars($first), get_object_vars($second), $identical); } /** * Find the first character position that differs * in two strings by binary chop. * @param string $first First string. * @param string $second String to compare with. * @return integer Position of first differing * character. * @access private */ protected function stringDiffersAt($first, $second) { if (! $first || ! $second) { return 0; } if (strlen($first) < strlen($second)) { list($first, $second) = array($second, $first); } $position = 0; $step = strlen($first); while ($step > 1) { $step = (integer)(($step + 1) / 2); if (strncmp($first, $second, $position + $step) == 0) { $position += $step; } } return $position; } /** * Sends a formatted dump of a variable to a string. * @param mixed $variable Variable to display. * @return string Output from print_r(). * @access public */ function dump($variable) { ob_start(); print_r($variable); $formatted = ob_get_contents(); ob_end_clean(); return $formatted; } } ?>Swift-4.2.1/test-suite/lib/simpletest/eclipse.php100644 0 0 23245 12000050366 17161 0ustar 0 0 listener = &$listener; $this->SimpleScorer(); $this->case = ""; $this->group = ""; $this->method = ""; $this->cc = $cc; $this->error = false; $this->fail = false; } /** * Means to display human readable object comparisons. * @return SimpleDumper Visual comparer. */ function getDumper() { return new SimpleDumper(); } /** * Localhost connection from Eclipse. * @param integer $port Port to connect to Eclipse. * @param string $host Normally localhost. * @return SimpleSocket Connection to Eclipse. */ function &createListener($port, $host="127.0.0.1"){ $tmplistener = &new SimpleSocket($host, $port, 5); return $tmplistener; } /** * Wraps the test in an output buffer. * @param SimpleInvoker $invoker Current test runner. * @return EclipseInvoker Decorator with output buffering. * @access public */ function &createInvoker(&$invoker){ $eclinvoker = &new EclipseInvoker($invoker, $this->listener); return $eclinvoker; } /** * C style escaping. * @param string $raw String with backslashes, quotes and whitespace. * @return string Replaced with C backslashed tokens. */ function escapeVal($raw){ $needle = array("\\","\"","/","\b","\f","\n","\r","\t"); $replace = array('\\\\','\"','\/','\b','\f','\n','\r','\t'); return str_replace($needle, $replace, $raw); } /** * Stash the first passing item. Clicking the test * item goes to first pass. * @param string $message Test message, but we only wnat the first. * @access public */ function paintPass($message){ if (! $this->pass){ $this->message = $this->escapeVal($message); } $this->pass = true; } /** * Stash the first failing item. Clicking the test * item goes to first fail. * @param string $message Test message, but we only wnat the first. * @access public */ function paintFail($message){ //only get the first failure or error if (! $this->fail && ! $this->error){ $this->fail = true; $this->message = $this->escapeVal($message); $this->listener->write('{status:"fail",message:"'.$this->message.'",group:"'.$this->group.'",case:"'.$this->case.'",method:"'.$this->method.'"}'); } } /** * Stash the first error. Clicking the test * item goes to first error. * @param string $message Test message, but we only wnat the first. * @access public */ function paintError($message){ if (! $this->fail && ! $this->error){ $this->error = true; $this->message = $this->escapeVal($message); $this->listener->write('{status:"error",message:"'.$this->message.'",group:"'.$this->group.'",case:"'.$this->case.'",method:"'.$this->method.'"}'); } } /** * Stash the first exception. Clicking the test * item goes to first message. * @param string $message Test message, but we only wnat the first. * @access public */ function paintException($exception){ if (! $this->fail && ! $this->error){ $this->error = true; $message = 'Unexpected exception of type[' . get_class($exception) . '] with message [' . $exception->getMessage() . '] in [' . $exception->getFile() .' line '. $exception->getLine() . ']'; $this->message = $this->escapeVal($message); $this->listener->write( '{status:"error",message:"' . $this->message . '",group:"' . $this->group . '",case:"' . $this->case . '",method:"' . $this->method . '"}'); } } /** * We don't display any special header. * @param string $test_name First test top level * to start. * @access public */ function paintHeader($test_name) { } /** * We don't display any special footer. * @param string $test_name The top level test. * @access public */ function paintFooter($test_name) { } /** * Paints nothing at the start of a test method, but stash * the method name for later. * @param string $test_name Name of test that is starting. * @access public */ function paintMethodStart($method) { $this->pass = false; $this->fail = false; $this->error = false; $this->method = $this->escapeVal($method); } /** * Only send one message if the test passes, after that * suppress the message. * @param string $test_name Name of test that is ending. * @access public */ function paintMethodEnd($method){ if ($this->fail || $this->error || ! $this->pass){ } else { $this->listener->write( '{status:"pass",message:"' . $this->message . '",group:"' . $this->group . '",case:"' . $this->case . '",method:"' . $this->method . '"}'); } } /** * Stashes the test case name for the later failure message. * @param string $test_name Name of test or other label. * @access public */ function paintCaseStart($case){ $this->case = $this->escapeVal($case); } /** * Drops the name. * @param string $test_name Name of test or other label. * @access public */ function paintCaseEnd($case){ $this->case = ""; } /** * Stashes the name of the test suite. Starts test coverage * if enabled. * @param string $group Name of test or other label. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($group, $size){ $this->group = $this->escapeVal($group); if ($this->cc){ if (extension_loaded('xdebug')){ xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); } } } /** * Paints coverage report if enabled. * @param string $group Name of test or other label. * @access public */ function paintGroupEnd($group){ $this->group = ""; $cc = ""; if ($this->cc){ if (extension_loaded('xdebug')){ $arrfiles = xdebug_get_code_coverage(); xdebug_stop_code_coverage(); $thisdir = dirname(__FILE__); $thisdirlen = strlen($thisdir); foreach ($arrfiles as $index=>$file){ if (substr($index, 0, $thisdirlen)===$thisdir){ continue; } $lcnt = 0; $ccnt = 0; foreach ($file as $line){ if ($line == -2){ continue; } $lcnt++; if ($line==1){ $ccnt++; } } if ($lcnt > 0){ $cc .= round(($ccnt/$lcnt) * 100, 2) . '%'; }else{ $cc .= "0.00%"; } $cc.= "\t". $index . "\n"; } } } $this->listener->write('{status:"coverage",message:"' . EclipseReporter::escapeVal($cc) . '"}'); } } /** * Invoker decorator for Eclipse. Captures output until * the end of the test. * @package SimpleTest * @subpackage Eclipse */ class EclipseInvoker extends SimpleInvokerDecorator{ function __construct(&$invoker, &$listener) { $this->listener = &$listener; $this->SimpleInvokerDecorator($invoker); } /** * Starts output buffering. * @param string $method Test method to call. * @access public */ function before($method){ ob_start(); $this->invoker->before($method); } /** * Stops output buffering and send the captured output * to the listener. * @param string $method Test method to call. * @access public */ function after($method) { $this->invoker->after($method); $output = ob_get_contents(); ob_end_clean(); if ($output !== ""){ $result = $this->listener->write('{status:"info",message:"' . EclipseReporter::escapeVal($output) . '"}'); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/encoding.php100644 0 0 34555 12000050366 17331 0ustar 0 0 key = $key; $this->value = $value; } /** * The pair as a single string. * @return string Encoded pair. * @access public */ function asRequest() { return urlencode($this->key) . '=' . urlencode($this->value); } /** * The MIME part as a string. * @return string MIME part encoding. * @access public */ function asMime() { $part = 'Content-Disposition: form-data; '; $part .= "name=\"" . $this->key . "\"\r\n"; $part .= "\r\n" . $this->value; return $part; } /** * Is this the value we are looking for? * @param string $key Identifier. * @return boolean True if matched. * @access public */ function isKey($key) { return $key == $this->key; } /** * Is this the value we are looking for? * @return string Identifier. * @access public */ function getKey() { return $this->key; } /** * Is this the value we are looking for? * @return string Content. * @access public */ function getValue() { return $this->value; } } /** * Single post parameter. * @package SimpleTest * @subpackage WebTester */ class SimpleAttachment { private $key; private $content; private $filename; /** * Stashes the data for rendering later. * @param string $key Key to add value to. * @param string $content Raw data. * @param hash $filename Original filename. */ function __construct($key, $content, $filename) { $this->key = $key; $this->content = $content; $this->filename = $filename; } /** * The pair as a single string. * @return string Encoded pair. * @access public */ function asRequest() { return ''; } /** * The MIME part as a string. * @return string MIME part encoding. * @access public */ function asMime() { $part = 'Content-Disposition: form-data; '; $part .= 'name="' . $this->key . '"; '; $part .= 'filename="' . $this->filename . '"'; $part .= "\r\nContent-Type: " . $this->deduceMimeType(); $part .= "\r\n\r\n" . $this->content; return $part; } /** * Attempts to figure out the MIME type from the * file extension and the content. * @return string MIME type. * @access private */ protected function deduceMimeType() { if ($this->isOnlyAscii($this->content)) { return 'text/plain'; } return 'application/octet-stream'; } /** * Tests each character is in the range 0-127. * @param string $ascii String to test. * @access private */ protected function isOnlyAscii($ascii) { for ($i = 0, $length = strlen($ascii); $i < $length; $i++) { if (ord($ascii[$i]) > 127) { return false; } } return true; } /** * Is this the value we are looking for? * @param string $key Identifier. * @return boolean True if matched. * @access public */ function isKey($key) { return $key == $this->key; } /** * Is this the value we are looking for? * @return string Identifier. * @access public */ function getKey() { return $this->key; } /** * Is this the value we are looking for? * @return string Content. * @access public */ function getValue() { return $this->filename; } } /** * Bundle of GET/POST parameters. Can include * repeated parameters. * @package SimpleTest * @subpackage WebTester */ class SimpleEncoding { private $request; /** * Starts empty. * @param array $query Hash of parameters. * Multiple values are * as lists on a single key. * @access public */ function __construct($query = false) { if (! $query) { $query = array(); } $this->clear(); $this->merge($query); } /** * Empties the request of parameters. * @access public */ function clear() { $this->request = array(); } /** * Adds a parameter to the query. * @param string $key Key to add value to. * @param string/array $value New data. * @access public */ function add($key, $value) { if ($value === false) { return; } if (is_array($value)) { foreach ($value as $item) { $this->addPair($key, $item); } } else { $this->addPair($key, $value); } } /** * Adds a new value into the request. * @param string $key Key to add value to. * @param string/array $value New data. * @access private */ protected function addPair($key, $value) { $this->request[] = new SimpleEncodedPair($key, $value); } /** * Adds a MIME part to the query. Does nothing for a * form encoded packet. * @param string $key Key to add value to. * @param string $content Raw data. * @param hash $filename Original filename. * @access public */ function attach($key, $content, $filename) { $this->request[] = new SimpleAttachment($key, $content, $filename); } /** * Adds a set of parameters to this query. * @param array/SimpleQueryString $query Multiple values are * as lists on a single key. * @access public */ function merge($query) { if (is_object($query)) { $this->request = array_merge($this->request, $query->getAll()); } elseif (is_array($query)) { foreach ($query as $key => $value) { $this->add($key, $value); } } } /** * Accessor for single value. * @return string/array False if missing, string * if present and array if * multiple entries. * @access public */ function getValue($key) { $values = array(); foreach ($this->request as $pair) { if ($pair->isKey($key)) { $values[] = $pair->getValue(); } } if (count($values) == 0) { return false; } elseif (count($values) == 1) { return $values[0]; } else { return $values; } } /** * Accessor for listing of pairs. * @return array All pair objects. * @access public */ function getAll() { return $this->request; } /** * Renders the query string as a URL encoded * request part. * @return string Part of URL. * @access protected */ protected function encode() { $statements = array(); foreach ($this->request as $pair) { if ($statement = $pair->asRequest()) { $statements[] = $statement; } } return implode('&', $statements); } } /** * Bundle of GET parameters. Can include * repeated parameters. * @package SimpleTest * @subpackage WebTester */ class SimpleGetEncoding extends SimpleEncoding { /** * Starts empty. * @param array $query Hash of parameters. * Multiple values are * as lists on a single key. * @access public */ function __construct($query = false) { parent::__construct($query); } /** * HTTP request method. * @return string Always GET. * @access public */ function getMethod() { return 'GET'; } /** * Writes no extra headers. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeHeadersTo(&$socket) { } /** * No data is sent to the socket as the data is encoded into * the URL. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeTo(&$socket) { } /** * Renders the query string as a URL encoded * request part for attaching to a URL. * @return string Part of URL. * @access public */ function asUrlRequest() { return $this->encode(); } } /** * Bundle of URL parameters for a HEAD request. * @package SimpleTest * @subpackage WebTester */ class SimpleHeadEncoding extends SimpleGetEncoding { /** * Starts empty. * @param array $query Hash of parameters. * Multiple values are * as lists on a single key. * @access public */ function SimpleHeadEncoding($query = false) { $this->SimpleGetEncoding($query); } /** * HTTP request method. * @return string Always HEAD. * @access public */ function getMethod() { return 'HEAD'; } } /** * Bundle of POST parameters. Can include * repeated parameters. * @package SimpleTest * @subpackage WebTester */ class SimplePostEncoding extends SimpleEncoding { /** * Starts empty. * @param array $query Hash of parameters. * Multiple values are * as lists on a single key. * @access public */ function __construct($query = false) { if (is_array($query) and $this->hasMoreThanOneLevel($query)) { $query = $this->rewriteArrayWithMultipleLevels($query); } parent::__construct($query); } function hasMoreThanOneLevel($query) { foreach ($query as $key => $value) { if (is_array($value)) { return true; } } return false; } function rewriteArrayWithMultipleLevels($query) { $query_ = array(); foreach ($query as $key => $value) { if (is_array($value)) { foreach ($value as $sub_key => $sub_value) { $query_[$key."[".$sub_key."]"] = $sub_value; } } else { $query_[$key] = $value; } } if ($this->hasMoreThanOneLevel($query_)) { $query_ = $this->rewriteArrayWithMultipleLevels($query_); } return $query_; } /** * HTTP request method. * @return string Always POST. * @access public */ function getMethod() { return 'POST'; } /** * Dispatches the form headers down the socket. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeHeadersTo(&$socket) { $socket->write("Content-Length: " . (integer)strlen($this->encode()) . "\r\n"); $socket->write("Content-Type: application/x-www-form-urlencoded\r\n"); } /** * Dispatches the form data down the socket. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeTo(&$socket) { $socket->write($this->encode()); } /** * Renders the query string as a URL encoded * request part for attaching to a URL. * @return string Part of URL. * @access public */ function asUrlRequest() { return ''; } } /** * Bundle of POST parameters in the multipart * format. Can include file uploads. * @package SimpleTest * @subpackage WebTester */ class SimpleMultipartEncoding extends SimplePostEncoding { private $boundary; /** * Starts empty. * @param array $query Hash of parameters. * Multiple values are * as lists on a single key. * @access public */ function __construct($query = false, $boundary = false) { parent::__construct($query); $this->boundary = ($boundary === false ? uniqid('st') : $boundary); } /** * Dispatches the form headers down the socket. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeHeadersTo(&$socket) { $socket->write("Content-Length: " . (integer)strlen($this->encode()) . "\r\n"); $socket->write("Content-Type: multipart/form-data, boundary=" . $this->boundary . "\r\n"); } /** * Dispatches the form data down the socket. * @param SimpleSocket $socket Socket to write to. * @access public */ function writeTo(&$socket) { $socket->write($this->encode()); } /** * Renders the query string as a URL encoded * request part. * @return string Part of URL. * @access public */ function encode() { $stream = ''; foreach ($this->getAll() as $pair) { $stream .= "--" . $this->boundary . "\r\n"; $stream .= $pair->asMime() . "\r\n"; } $stream .= "--" . $this->boundary . "--\r\n"; return $stream; } } ?>Swift-4.2.1/test-suite/lib/simpletest/errors.php100644 0 0 20566 12000050366 17054 0ustar 0 0 createErrorQueue(); set_error_handler('SimpleTestErrorHandler'); parent::invoke($method); restore_error_handler(); $queue->tally(); } /** * Wires up the error queue for a single test. * @return SimpleErrorQueue Queue connected to the test. * @access private */ protected function createErrorQueue() { $context = SimpleTest::getContext(); $test = $this->getTestCase(); $queue = $context->get('SimpleErrorQueue'); $queue->setTestCase($test); return $queue; } } /** * Error queue used to record trapped * errors. * @package SimpleTest * @subpackage UnitTester */ class SimpleErrorQueue { private $queue; private $expectation_queue; private $test; private $using_expect_style = false; /** * Starts with an empty queue. */ function __construct() { $this->clear(); } /** * Discards the contents of the error queue. * @access public */ function clear() { $this->queue = array(); $this->expectation_queue = array(); } /** * Sets the currently running test case. * @param SimpleTestCase $test Test case to send messages to. * @access public */ function setTestCase($test) { $this->test = $test; } /** * Sets up an expectation of an error. If this is * not fulfilled at the end of the test, a failure * will occour. If the error does happen, then this * will cancel it out and send a pass message. * @param SimpleExpectation $expected Expected error match. * @param string $message Message to display. * @access public */ function expectError($expected, $message) { array_push($this->expectation_queue, array($expected, $message)); } /** * Adds an error to the front of the queue. * @param integer $severity PHP error code. * @param string $content Text of error. * @param string $filename File error occoured in. * @param integer $line Line number of error. * @access public */ function add($severity, $content, $filename, $line) { $content = str_replace('%', '%%', $content); $this->testLatestError($severity, $content, $filename, $line); } /** * Any errors still in the queue are sent to the test * case. Any unfulfilled expectations trigger failures. * @access public */ function tally() { while (list($severity, $message, $file, $line) = $this->extract()) { $severity = $this->getSeverityAsString($severity); $this->test->error($severity, $message, $file, $line); } while (list($expected, $message) = $this->extractExpectation()) { $this->test->assert($expected, false, "%s -> Expected error not caught"); } } /** * Tests the error against the most recent expected * error. * @param integer $severity PHP error code. * @param string $content Text of error. * @param string $filename File error occoured in. * @param integer $line Line number of error. * @access private */ protected function testLatestError($severity, $content, $filename, $line) { if ($expectation = $this->extractExpectation()) { list($expected, $message) = $expectation; $this->test->assert($expected, $content, sprintf( $message, "%s -> PHP error [$content] severity [" . $this->getSeverityAsString($severity) . "] in [$filename] line [$line]")); } else { $this->test->error($severity, $content, $filename, $line); } } /** * Pulls the earliest error from the queue. * @return mixed False if none, or a list of error * information. Elements are: severity * as the PHP error code, the error message, * the file with the error, the line number * and a list of PHP super global arrays. * @access public */ function extract() { if (count($this->queue)) { return array_shift($this->queue); } return false; } /** * Pulls the earliest expectation from the queue. * @return SimpleExpectation False if none. * @access private */ protected function extractExpectation() { if (count($this->expectation_queue)) { return array_shift($this->expectation_queue); } return false; } /** * Converts an error code into it's string * representation. * @param $severity PHP integer error code. * @return String version of error code. * @access public */ static function getSeverityAsString($severity) { static $map = array( E_STRICT => 'E_STRICT', E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE', E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING', E_COMPILE_ERROR => 'E_COMPILE_ERROR', E_COMPILE_WARNING => 'E_COMPILE_WARNING', E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING', E_USER_NOTICE => 'E_USER_NOTICE'); if (defined('E_RECOVERABLE_ERROR')) { $map[E_RECOVERABLE_ERROR] = 'E_RECOVERABLE_ERROR'; } if (defined('E_DEPRECATED')) { $map[E_DEPRECATED] = 'E_DEPRECATED'; } return $map[$severity]; } } /** * Error handler that simply stashes any errors into the global * error queue. Simulates the existing behaviour with respect to * logging errors, but this feature may be removed in future. * @param $severity PHP error code. * @param $message Text of error. * @param $filename File error occoured in. * @param $line Line number of error. * @param $super_globals Hash of PHP super global arrays. * @access public */ function SimpleTestErrorHandler($severity, $message, $filename = null, $line = null, $super_globals = null, $mask = null) { $severity = $severity & error_reporting(); if ($severity) { restore_error_handler(); if (IsNotCausedBySimpleTest($message)) { if (ini_get('log_errors')) { $label = SimpleErrorQueue::getSeverityAsString($severity); error_log("$label: $message in $filename on line $line"); } $queue = SimpleTest::getContext()->get('SimpleErrorQueue'); $queue->add($severity, $message, $filename, $line); } set_error_handler('SimpleTestErrorHandler'); } return true; } /** * Certain messages can be caused by the unit tester itself. * These have to be filtered. * @param string $message Message to filter. * @return boolean True if genuine failure. */ function IsNotCausedBySimpleTest($message) { return ! preg_match('/returned by reference/', $message); } ?>Swift-4.2.1/test-suite/lib/simpletest/exceptions.php100644 0 0 14013 12000050366 17707 0ustar 0 0 get('SimpleExceptionTrap'); $trap->clear(); try { $has_thrown = false; parent::invoke($method); } catch (Exception $exception) { $has_thrown = true; if (! $trap->isExpected($this->getTestCase(), $exception)) { $this->getTestCase()->exception($exception); } $trap->clear(); } if ($message = $trap->getOutstanding()) { $this->getTestCase()->fail($message); } if ($has_thrown) { try { parent::getTestCase()->tearDown(); } catch (Exception $e) { } } } } /** * Tests exceptions either by type or the exact * exception. This could be improved to accept * a pattern expectation to test the error * message, but that will have to come later. * @package SimpleTest * @subpackage UnitTester */ class ExceptionExpectation extends SimpleExpectation { private $expected; /** * Sets up the conditions to test against. * If the expected value is a string, then * it will act as a test of the class name. * An exception as the comparison will * trigger an identical match. Writing this * down now makes it look doubly dumb. I hope * come up with a better scheme later. * @param mixed $expected A class name or an actual * exception to compare with. * @param string $message Message to display. */ function __construct($expected, $message = '%s') { $this->expected = $expected; parent::__construct($message); } /** * Carry out the test. * @param Exception $compare Value to check. * @return boolean True if matched. */ function test($compare) { if (is_string($this->expected)) { return ($compare instanceof $this->expected); } if (get_class($compare) != get_class($this->expected)) { return false; } return $compare->getMessage() == $this->expected->getMessage(); } /** * Create the message to display describing the test. * @param Exception $compare Exception to match. * @return string Final message. */ function testMessage($compare) { if (is_string($this->expected)) { return "Exception [" . $this->describeException($compare) . "] should be type [" . $this->expected . "]"; } return "Exception [" . $this->describeException($compare) . "] should match [" . $this->describeException($this->expected) . "]"; } /** * Summary of an Exception object. * @param Exception $compare Exception to describe. * @return string Text description. */ protected function describeException($exception) { return get_class($exception) . ": " . $exception->getMessage(); } } /** * Stores expected exceptions for when they * get thrown. Saves the irritating try...catch * block. * @package SimpleTest * @subpackage UnitTester */ class SimpleExceptionTrap { private $expected; private $message; /** * Clears down the queue ready for action. */ function __construct() { $this->clear(); } /** * Sets up an expectation of an exception. * This has the effect of intercepting an * exception that matches. * @param SimpleExpectation $expected Expected exception to match. * @param string $message Message to display. * @access public */ function expectException($expected = false, $message = '%s') { if ($expected === false) { $expected = new AnythingExpectation(); } if (! SimpleExpectation::isExpectation($expected)) { $expected = new ExceptionExpectation($expected); } $this->expected = $expected; $this->message = $message; } /** * Compares the expected exception with any * in the queue. Issues a pass or fail and * returns the state of the test. * @param SimpleTestCase $test Test case to send messages to. * @param Exception $exception Exception to compare. * @return boolean False on no match. */ function isExpected($test, $exception) { if ($this->expected) { return $test->assert($this->expected, $exception, $this->message); } return false; } /** * Tests for any left over exception. * @return string/false The failure message or false if none. */ function getOutstanding() { return sprintf($this->message, 'Failed to trap exception'); } /** * Discards the contents of the error queue. */ function clear() { $this->expected = false; $this->message = false; } } ?>Swift-4.2.1/test-suite/lib/simpletest/expectation.php100644 0 0 65650 12000050366 20066 0ustar 0 0 message = $message; } /** * Tests the expectation. True if correct. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public * @abstract */ function test($compare) { } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public * @abstract */ function testMessage($compare) { } /** * Overlays the generated message onto the stored user * message. An additional message can be interjected. * @param mixed $compare Comparison value. * @param SimpleDumper $dumper For formatting the results. * @return string Description of success * or failure. * @access public */ function overlayMessage($compare, $dumper) { $this->dumper = $dumper; return sprintf($this->message, $this->testMessage($compare)); } /** * Accessor for the dumper. * @return SimpleDumper Current value dumper. * @access protected */ protected function getDumper() { if (! $this->dumper) { $dumper = new SimpleDumper(); return $dumper; } return $this->dumper; } /** * Test to see if a value is an expectation object. * A useful utility method. * @param mixed $expectation Hopefully an Expectation * class. * @return boolean True if descended from * this class. * @access public */ static function isExpectation($expectation) { return is_object($expectation) && SimpleTestCompatibility::isA($expectation, 'SimpleExpectation'); } } /** * A wildcard expectation always matches. * @package SimpleTest * @subpackage MockObjects */ class AnythingExpectation extends SimpleExpectation { /** * Tests the expectation. Always true. * @param mixed $compare Ignored. * @return boolean True. * @access public */ function test($compare) { return true; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return 'Anything always matches [' . $dumper->describeValue($compare) . ']'; } } /** * An expectation that never matches. * @package SimpleTest * @subpackage MockObjects */ class FailedExpectation extends SimpleExpectation { /** * Tests the expectation. Always false. * @param mixed $compare Ignored. * @return boolean True. * @access public */ function test($compare) { return false; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return 'Failed expectation never matches [' . $dumper->describeValue($compare) . ']'; } } /** * An expectation that passes on boolean true. * @package SimpleTest * @subpackage MockObjects */ class TrueExpectation extends SimpleExpectation { /** * Tests the expectation. * @param mixed $compare Should be true. * @return boolean True on match. * @access public */ function test($compare) { return (boolean)$compare; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return 'Expected true, got [' . $dumper->describeValue($compare) . ']'; } } /** * An expectation that passes on boolean false. * @package SimpleTest * @subpackage MockObjects */ class FalseExpectation extends SimpleExpectation { /** * Tests the expectation. * @param mixed $compare Should be false. * @return boolean True on match. * @access public */ function test($compare) { return ! (boolean)$compare; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return 'Expected false, got [' . $dumper->describeValue($compare) . ']'; } } /** * Test for equality. * @package SimpleTest * @subpackage UnitTester */ class EqualExpectation extends SimpleExpectation { private $value; /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $message = '%s') { parent::__construct($message); $this->value = $value; } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (($this->value == $compare) && ($compare == $this->value)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return "Equal expectation [" . $this->dumper->describeValue($this->value) . "]"; } else { return "Equal expectation fails " . $this->dumper->describeDifference($this->value, $compare); } } /** * Accessor for comparison value. * @return mixed Held value to compare with. * @access protected */ protected function getValue() { return $this->value; } } /** * Test for inequality. * @package SimpleTest * @subpackage UnitTester */ class NotEqualExpectation extends EqualExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $message = '%s') { parent::__construct($value, $message); } /** * Tests the expectation. True if it differs from the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); if ($this->test($compare)) { return "Not equal expectation passes " . $dumper->describeDifference($this->getValue(), $compare); } else { return "Not equal expectation fails [" . $dumper->describeValue($this->getValue()) . "] matches"; } } } /** * Test for being within a range. * @package SimpleTest * @subpackage UnitTester */ class WithinMarginExpectation extends SimpleExpectation { private $upper; private $lower; /** * Sets the value to compare against and the fuzziness of * the match. Used for comparing floating point values. * @param mixed $value Test value to match. * @param mixed $margin Fuzziness of match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $margin, $message = '%s') { parent::__construct($message); $this->upper = $value + $margin; $this->lower = $value - $margin; } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (($compare <= $this->upper) && ($compare >= $this->lower)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return $this->withinMessage($compare); } else { return $this->outsideMessage($compare); } } /** * Creates a the message for being within the range. * @param mixed $compare Value being tested. * @access private */ protected function withinMessage($compare) { return "Within expectation [" . $this->dumper->describeValue($this->lower) . "] and [" . $this->dumper->describeValue($this->upper) . "]"; } /** * Creates a the message for being within the range. * @param mixed $compare Value being tested. * @access private */ protected function outsideMessage($compare) { if ($compare > $this->upper) { return "Outside expectation " . $this->dumper->describeDifference($compare, $this->upper); } else { return "Outside expectation " . $this->dumper->describeDifference($compare, $this->lower); } } } /** * Test for being outside of a range. * @package SimpleTest * @subpackage UnitTester */ class OutsideMarginExpectation extends WithinMarginExpectation { /** * Sets the value to compare against and the fuzziness of * the match. Used for comparing floating point values. * @param mixed $value Test value to not match. * @param mixed $margin Fuzziness of match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $margin, $message = '%s') { parent::__construct($value, $margin, $message); } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if (! $this->test($compare)) { return $this->withinMessage($compare); } else { return $this->outsideMessage($compare); } } } /** * Test for reference. * @package SimpleTest * @subpackage UnitTester */ class ReferenceExpectation { private $value; /** * Sets the reference value to compare against. * @param mixed $value Test reference to match. * @param string $message Customised message on failure. * @access public */ function __construct(&$value, $message = '%s') { $this->message = $message; $this->value = &$value; } /** * Tests the expectation. True if it exactly * references the held value. * @param mixed $compare Comparison reference. * @return boolean True if correct. * @access public */ function test(&$compare) { return SimpleTestCompatibility::isReference($this->value, $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return "Reference expectation [" . $this->dumper->describeValue($this->value) . "]"; } else { return "Reference expectation fails " . $this->dumper->describeDifference($this->value, $compare); } } /** * Overlays the generated message onto the stored user * message. An additional message can be interjected. * @param mixed $compare Comparison value. * @param SimpleDumper $dumper For formatting the results. * @return string Description of success * or failure. * @access public */ function overlayMessage($compare, $dumper) { $this->dumper = $dumper; return sprintf($this->message, $this->testMessage($compare)); } /** * Accessor for the dumper. * @return SimpleDumper Current value dumper. * @access protected */ protected function getDumper() { if (! $this->dumper) { $dumper = new SimpleDumper(); return $dumper; } return $this->dumper; } } /** * Test for identity. * @package SimpleTest * @subpackage UnitTester */ class IdenticalExpectation extends EqualExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $message = '%s') { parent::__construct($value, $message); } /** * Tests the expectation. True if it exactly * matches the held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return SimpleTestCompatibility::isIdentical($this->getValue(), $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); if ($this->test($compare)) { return "Identical expectation [" . $dumper->describeValue($this->getValue()) . "]"; } else { return "Identical expectation [" . $dumper->describeValue($this->getValue()) . "] fails with [" . $dumper->describeValue($compare) . "] " . $dumper->describeDifference($this->getValue(), $compare, TYPE_MATTERS); } } } /** * Test for non-identity. * @package SimpleTest * @subpackage UnitTester */ class NotIdenticalExpectation extends IdenticalExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function __construct($value, $message = '%s') { parent::__construct($value, $message); } /** * Tests the expectation. True if it differs from the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); if ($this->test($compare)) { return "Not identical expectation passes " . $dumper->describeDifference($this->getValue(), $compare, TYPE_MATTERS); } else { return "Not identical expectation [" . $dumper->describeValue($this->getValue()) . "] matches"; } } } /** * Test for a pattern using Perl regex rules. * @package SimpleTest * @subpackage UnitTester */ class PatternExpectation extends SimpleExpectation { private $pattern; /** * Sets the value to compare against. * @param string $pattern Pattern to search for. * @param string $message Customised message on failure. * @access public */ function __construct($pattern, $message = '%s') { parent::__construct($message); $this->pattern = $pattern; } /** * Accessor for the pattern. * @return string Perl regex as string. * @access protected */ protected function getPattern() { return $this->pattern; } /** * Tests the expectation. True if the Perl regex * matches the comparison value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (boolean)preg_match($this->getPattern(), $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return $this->describePatternMatch($this->getPattern(), $compare); } else { $dumper = $this->getDumper(); return "Pattern [" . $this->getPattern() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } } /** * Describes a pattern match including the string * found and it's position. * @param string $pattern Regex to match against. * @param string $subject Subject to search. * @access protected */ protected function describePatternMatch($pattern, $subject) { preg_match($pattern, $subject, $matches); $position = strpos($subject, $matches[0]); $dumper = $this->getDumper(); return "Pattern [$pattern] detected at character [$position] in [" . $dumper->describeValue($subject) . "] as [" . $matches[0] . "] in region [" . $dumper->clipString($subject, 100, $position) . "]"; } } /** * Fail if a pattern is detected within the * comparison. * @package SimpleTest * @subpackage UnitTester */ class NoPatternExpectation extends PatternExpectation { /** * Sets the reject pattern * @param string $pattern Pattern to search for. * @param string $message Customised message on failure. * @access public */ function __construct($pattern, $message = '%s') { parent::__construct($pattern, $message); } /** * Tests the expectation. False if the Perl regex * matches the comparison value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param string $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { $dumper = $this->getDumper(); return "Pattern [" . $this->getPattern() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } else { return $this->describePatternMatch($this->getPattern(), $compare); } } } /** * Tests either type or class name if it's an object. * @package SimpleTest * @subpackage UnitTester */ class IsAExpectation extends SimpleExpectation { private $type; /** * Sets the type to compare with. * @param string $type Type or class name. * @param string $message Customised message on failure. * @access public */ function __construct($type, $message = '%s') { parent::__construct($message); $this->type = $type; } /** * Accessor for type to check against. * @return string Type or class name. * @access protected */ protected function getType() { return $this->type; } /** * Tests the expectation. True if the type or * class matches the string value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { if (is_object($compare)) { return SimpleTestCompatibility::isA($compare, $this->type); } else { return (strtolower(gettype($compare)) == $this->canonicalType($this->type)); } } /** * Coerces type name into a gettype() match. * @param string $type User type. * @return string Simpler type. * @access private */ protected function canonicalType($type) { $type = strtolower($type); $map = array( 'bool' => 'boolean', 'float' => 'double', 'real' => 'double', 'int' => 'integer'); if (isset($map[$type])) { $type = $map[$type]; } return $type; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return "Value [" . $dumper->describeValue($compare) . "] should be type [" . $this->type . "]"; } } /** * Tests either type or class name if it's an object. * Will succeed if the type does not match. * @package SimpleTest * @subpackage UnitTester */ class NotAExpectation extends IsAExpectation { private $type; /** * Sets the type to compare with. * @param string $type Type or class name. * @param string $message Customised message on failure. * @access public */ function __construct($type, $message = '%s') { parent::__construct($type, $message); } /** * Tests the expectation. False if the type or * class matches the string value. * @param string $compare Comparison value. * @return boolean True if different. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); return "Value [" . $dumper->describeValue($compare) . "] should not be type [" . $this->getType() . "]"; } } /** * Tests for existance of a method in an object * @package SimpleTest * @subpackage UnitTester */ class MethodExistsExpectation extends SimpleExpectation { private $method; /** * Sets the value to compare against. * @param string $method Method to check. * @param string $message Customised message on failure. * @access public * @return void */ function __construct($method, $message = '%s') { parent::__construct($message); $this->method = &$method; } /** * Tests the expectation. True if the method exists in the test object. * @param string $compare Comparison method name. * @return boolean True if correct. * @access public */ function test($compare) { return (boolean)(is_object($compare) && method_exists($compare, $this->method)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); if (! is_object($compare)) { return 'No method on non-object [' . $dumper->describeValue($compare) . ']'; } $method = $this->method; return "Object [" . $dumper->describeValue($compare) . "] should contain method [$method]"; } } ?>Swift-4.2.1/test-suite/lib/simpletest/form.php100644 0 0 27033 12000050366 16477 0ustar 0 0 method = $tag->getAttribute('method'); $this->action = $this->createAction($tag->getAttribute('action'), $page); $this->encoding = $this->setEncodingClass($tag); $this->default_target = false; $this->id = $tag->getAttribute('id'); $this->buttons = array(); $this->images = array(); $this->widgets = array(); $this->radios = array(); $this->checkboxes = array(); } /** * Creates the request packet to be sent by the form. * @param SimpleTag $tag Form tag to read. * @return string Packet class. * @access private */ protected function setEncodingClass($tag) { if (strtolower($tag->getAttribute('method')) == 'post') { if (strtolower($tag->getAttribute('enctype')) == 'multipart/form-data') { return 'SimpleMultipartEncoding'; } return 'SimplePostEncoding'; } return 'SimpleGetEncoding'; } /** * Sets the frame target within a frameset. * @param string $frame Name of frame. * @access public */ function setDefaultTarget($frame) { $this->default_target = $frame; } /** * Accessor for method of form submission. * @return string Either get or post. * @access public */ function getMethod() { return ($this->method ? strtolower($this->method) : 'get'); } /** * Combined action attribute with current location * to get an absolute form target. * @param string $action Action attribute from form tag. * @param SimpleUrl $base Page location. * @return SimpleUrl Absolute form target. */ protected function createAction($action, $page) { if (($action === '') || ($action === false)) { return $page->expandUrl($page->getUrl()); } return $page->expandUrl(new SimpleUrl($action));; } /** * Absolute URL of the target. * @return SimpleUrl URL target. * @access public */ function getAction() { $url = $this->action; if ($this->default_target && ! $url->getTarget()) { $url->setTarget($this->default_target); } return $url; } /** * Creates the encoding for the current values in the * form. * @return SimpleFormEncoding Request to submit. * @access private */ protected function encode() { $class = $this->encoding; $encoding = new $class(); for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { $this->widgets[$i]->write($encoding); } return $encoding; } /** * ID field of form for unique identification. * @return string Unique tag ID. * @access public */ function getId() { return $this->id; } /** * Adds a tag contents to the form. * @param SimpleWidget $tag Input tag to add. * @access public */ function addWidget($tag) { if (strtolower($tag->getAttribute('type')) == 'submit') { $this->buttons[] = $tag; } elseif (strtolower($tag->getAttribute('type')) == 'image') { $this->images[] = $tag; } elseif ($tag->getName()) { $this->setWidget($tag); } } /** * Sets the widget into the form, grouping radio * buttons if any. * @param SimpleWidget $tag Incoming form control. * @access private */ protected function setWidget($tag) { if (strtolower($tag->getAttribute('type')) == 'radio') { $this->addRadioButton($tag); } elseif (strtolower($tag->getAttribute('type')) == 'checkbox') { $this->addCheckbox($tag); } else { $this->widgets[] = &$tag; } } /** * Adds a radio button, building a group if necessary. * @param SimpleRadioButtonTag $tag Incoming form control. * @access private */ protected function addRadioButton($tag) { if (! isset($this->radios[$tag->getName()])) { $this->widgets[] = new SimpleRadioGroup(); $this->radios[$tag->getName()] = count($this->widgets) - 1; } $this->widgets[$this->radios[$tag->getName()]]->addWidget($tag); } /** * Adds a checkbox, making it a group on a repeated name. * @param SimpleCheckboxTag $tag Incoming form control. * @access private */ protected function addCheckbox($tag) { if (! isset($this->checkboxes[$tag->getName()])) { $this->widgets[] = $tag; $this->checkboxes[$tag->getName()] = count($this->widgets) - 1; } else { $index = $this->checkboxes[$tag->getName()]; if (! SimpleTestCompatibility::isA($this->widgets[$index], 'SimpleCheckboxGroup')) { $previous = $this->widgets[$index]; $this->widgets[$index] = new SimpleCheckboxGroup(); $this->widgets[$index]->addWidget($previous); } $this->widgets[$index]->addWidget($tag); } } /** * Extracts current value from form. * @param SimpleSelector $selector Criteria to apply. * @return string/array Value(s) as string or null * if not set. * @access public */ function getValue($selector) { for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { if ($selector->isMatch($this->widgets[$i])) { return $this->widgets[$i]->getValue(); } } foreach ($this->buttons as $button) { if ($selector->isMatch($button)) { return $button->getValue(); } } return null; } /** * Sets a widget value within the form. * @param SimpleSelector $selector Criteria to apply. * @param string $value Value to input into the widget. * @return boolean True if value is legal, false * otherwise. If the field is not * present, nothing will be set. * @access public */ function setField($selector, $value, $position=false) { $success = false; $_position = 0; for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { if ($selector->isMatch($this->widgets[$i])) { $_position++; if ($position === false or $_position === (int)$position) { if ($this->widgets[$i]->setValue($value)) { $success = true; } } } } return $success; } /** * Used by the page object to set widgets labels to * external label tags. * @param SimpleSelector $selector Criteria to apply. * @access public */ function attachLabelBySelector($selector, $label) { for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { if ($selector->isMatch($this->widgets[$i])) { if (method_exists($this->widgets[$i], 'setLabel')) { $this->widgets[$i]->setLabel($label); return; } } } } /** * Test to see if a form has a submit button. * @param SimpleSelector $selector Criteria to apply. * @return boolean True if present. * @access public */ function hasSubmit($selector) { foreach ($this->buttons as $button) { if ($selector->isMatch($button)) { return true; } } return false; } /** * Test to see if a form has an image control. * @param SimpleSelector $selector Criteria to apply. * @return boolean True if present. * @access public */ function hasImage($selector) { foreach ($this->images as $image) { if ($selector->isMatch($image)) { return true; } } return false; } /** * Gets the submit values for a selected button. * @param SimpleSelector $selector Criteria to apply. * @param hash $additional Additional data for the form. * @return SimpleEncoding Submitted values or false * if there is no such button * in the form. * @access public */ function submitButton($selector, $additional = false) { $additional = $additional ? $additional : array(); foreach ($this->buttons as $button) { if ($selector->isMatch($button)) { $encoding = $this->encode(); $button->write($encoding); if ($additional) { $encoding->merge($additional); } return $encoding; } } return false; } /** * Gets the submit values for an image. * @param SimpleSelector $selector Criteria to apply. * @param integer $x X-coordinate of click. * @param integer $y Y-coordinate of click. * @param hash $additional Additional data for the form. * @return SimpleEncoding Submitted values or false * if there is no such button in the * form. * @access public */ function submitImage($selector, $x, $y, $additional = false) { $additional = $additional ? $additional : array(); foreach ($this->images as $image) { if ($selector->isMatch($image)) { $encoding = $this->encode(); $image->write($encoding, $x, $y); if ($additional) { $encoding->merge($additional); } return $encoding; } } return false; } /** * Simply submits the form without the submit button * value. Used when there is only one button or it * is unimportant. * @return hash Submitted values. * @access public */ function submit() { return $this->encode(); } } ?>Swift-4.2.1/test-suite/lib/simpletest/frames.php100644 0 0 43770 12000050366 17017 0ustar 0 0 frameset = $page; $this->frames = array(); $this->focus = false; $this->names = array(); } /** * Adds a parsed page to the frameset. * @param SimplePage $page Frame page. * @param string $name Name of frame in frameset. * @access public */ function addFrame($page, $name = false) { $this->frames[] = $page; if ($name) { $this->names[$name] = count($this->frames) - 1; } } /** * Replaces existing frame with another. If the * frame is nested, then the call is passed down * one level. * @param array $path Path of frame in frameset. * @param SimplePage $page Frame source. * @access public */ function setFrame($path, $page) { $name = array_shift($path); if (isset($this->names[$name])) { $index = $this->names[$name]; } else { $index = $name - 1; } if (count($path) == 0) { $this->frames[$index] = &$page; return; } $this->frames[$index]->setFrame($path, $page); } /** * Accessor for current frame focus. Will be * false if no frame has focus. Will have the nested * frame focus if any. * @return array Labels or indexes of nested frames. * @access public */ function getFrameFocus() { if ($this->focus === false) { return array(); } return array_merge( array($this->getPublicNameFromIndex($this->focus)), $this->frames[$this->focus]->getFrameFocus()); } /** * Turns an internal array index into the frames list * into a public name, or if none, then a one offset * index. * @param integer $subject Internal index. * @return integer/string Public name. * @access private */ protected function getPublicNameFromIndex($subject) { foreach ($this->names as $name => $index) { if ($subject == $index) { return $name; } } return $subject + 1; } /** * Sets the focus by index. The integer index starts from 1. * If already focused and the target frame also has frames, * then the nested frame will be focused. * @param integer $choice Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocusByIndex($choice) { if (is_integer($this->focus)) { if ($this->frames[$this->focus]->hasFrames()) { return $this->frames[$this->focus]->setFrameFocusByIndex($choice); } } if (($choice < 1) || ($choice > count($this->frames))) { return false; } $this->focus = $choice - 1; return true; } /** * Sets the focus by name. If already focused and the * target frame also has frames, then the nested frame * will be focused. * @param string $name Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocus($name) { if (is_integer($this->focus)) { if ($this->frames[$this->focus]->hasFrames()) { return $this->frames[$this->focus]->setFrameFocus($name); } } if (in_array($name, array_keys($this->names))) { $this->focus = $this->names[$name]; return true; } return false; } /** * Clears the frame focus. * @access public */ function clearFrameFocus() { $this->focus = false; $this->clearNestedFramesFocus(); } /** * Clears the frame focus for any nested frames. * @access private */ protected function clearNestedFramesFocus() { for ($i = 0; $i < count($this->frames); $i++) { $this->frames[$i]->clearFrameFocus(); } } /** * Test for the presence of a frameset. * @return boolean Always true. * @access public */ function hasFrames() { return true; } /** * Accessor for frames information. * @return array/string Recursive hash of frame URL strings. * The key is either a numerical * index or the name attribute. * @access public */ function getFrames() { $report = array(); for ($i = 0; $i < count($this->frames); $i++) { $report[$this->getPublicNameFromIndex($i)] = $this->frames[$i]->getFrames(); } return $report; } /** * Accessor for raw text of either all the pages or * the frame in focus. * @return string Raw unparsed content. * @access public */ function getRaw() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getRaw(); } $raw = ''; for ($i = 0; $i < count($this->frames); $i++) { $raw .= $this->frames[$i]->getRaw(); } return $raw; } /** * Accessor for plain text of either all the pages or * the frame in focus. * @return string Plain text content. * @access public */ function getText() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getText(); } $raw = ''; for ($i = 0; $i < count($this->frames); $i++) { $raw .= ' ' . $this->frames[$i]->getText(); } return trim($raw); } /** * Accessor for last error. * @return string Error from last response. * @access public */ function getTransportError() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getTransportError(); } return $this->frameset->getTransportError(); } /** * Request method used to fetch this frame. * @return string GET, POST or HEAD. * @access public */ function getMethod() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getMethod(); } return $this->frameset->getMethod(); } /** * Original resource name. * @return SimpleUrl Current url. * @access public */ function getUrl() { if (is_integer($this->focus)) { $url = $this->frames[$this->focus]->getUrl(); $url->setTarget($this->getPublicNameFromIndex($this->focus)); } else { $url = $this->frameset->getUrl(); } return $url; } /** * Page base URL. * @return SimpleUrl Current url. * @access public */ function getBaseUrl() { if (is_integer($this->focus)) { $url = $this->frames[$this->focus]->getBaseUrl(); } else { $url = $this->frameset->getBaseUrl(); } return $url; } /** * Expands expandomatic URLs into fully qualified * URLs for the frameset page. * @param SimpleUrl $url Relative URL. * @return SimpleUrl Absolute URL. * @access public */ function expandUrl($url) { return $this->frameset->expandUrl($url); } /** * Original request data. * @return mixed Sent content. * @access public */ function getRequestData() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getRequestData(); } return $this->frameset->getRequestData(); } /** * Accessor for current MIME type. * @return string MIME type as string; e.g. 'text/html' * @access public */ function getMimeType() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getMimeType(); } return $this->frameset->getMimeType(); } /** * Accessor for last response code. * @return integer Last HTTP response code received. * @access public */ function getResponseCode() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getResponseCode(); } return $this->frameset->getResponseCode(); } /** * Accessor for last Authentication type. Only valid * straight after a challenge (401). * @return string Description of challenge type. * @access public */ function getAuthentication() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getAuthentication(); } return $this->frameset->getAuthentication(); } /** * Accessor for last Authentication realm. Only valid * straight after a challenge (401). * @return string Name of security realm. * @access public */ function getRealm() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getRealm(); } return $this->frameset->getRealm(); } /** * Accessor for outgoing header information. * @return string Header block. * @access public */ function getRequest() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getRequest(); } return $this->frameset->getRequest(); } /** * Accessor for raw header information. * @return string Header block. * @access public */ function getHeaders() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getHeaders(); } return $this->frameset->getHeaders(); } /** * Accessor for parsed title. * @return string Title or false if no title is present. * @access public */ function getTitle() { return $this->frameset->getTitle(); } /** * Accessor for a list of all fixed links. * @return array List of urls as strings. * @access public */ function getUrls() { if (is_integer($this->focus)) { return $this->frames[$this->focus]->getUrls(); } $urls = array(); foreach ($this->frames as $frame) { $urls = array_merge($urls, $frame->getUrls()); } return array_values(array_unique($urls)); } /** * Accessor for URLs by the link label. Label will match * regardess of whitespace issues and case. * @param string $label Text of link. * @return array List of links with that label. * @access public */ function getUrlsByLabel($label) { if (is_integer($this->focus)) { return $this->tagUrlsWithFrame( $this->frames[$this->focus]->getUrlsByLabel($label), $this->focus); } $urls = array(); foreach ($this->frames as $index => $frame) { $urls = array_merge( $urls, $this->tagUrlsWithFrame( $frame->getUrlsByLabel($label), $index)); } return $urls; } /** * Accessor for a URL by the id attribute. If in a frameset * then the first link found with that ID attribute is * returned only. Focus on a frame if you want one from * a specific part of the frameset. * @param string $id Id attribute of link. * @return string URL with that id. * @access public */ function getUrlById($id) { foreach ($this->frames as $index => $frame) { if ($url = $frame->getUrlById($id)) { if (! $url->gettarget()) { $url->setTarget($this->getPublicNameFromIndex($index)); } return $url; } } return false; } /** * Attaches the intended frame index to a list of URLs. * @param array $urls List of SimpleUrls. * @param string $frame Name of frame or index. * @return array List of tagged URLs. * @access private */ protected function tagUrlsWithFrame($urls, $frame) { $tagged = array(); foreach ($urls as $url) { if (! $url->getTarget()) { $url->setTarget($this->getPublicNameFromIndex($frame)); } $tagged[] = $url; } return $tagged; } /** * Finds a held form by button label. Will only * search correctly built forms. * @param SimpleSelector $selector Button finder. * @return SimpleForm Form object containing * the button. * @access public */ function getFormBySubmit($selector) { return $this->findForm('getFormBySubmit', $selector); } /** * Finds a held form by image using a selector. * Will only search correctly built forms. The first * form found either within the focused frame, or * across frames, will be the one returned. * @param SimpleSelector $selector Image finder. * @return SimpleForm Form object containing * the image. * @access public */ function getFormByImage($selector) { return $this->findForm('getFormByImage', $selector); } /** * Finds a held form by the form ID. A way of * identifying a specific form when we have control * of the HTML code. The first form found * either within the focused frame, or across frames, * will be the one returned. * @param string $id Form label. * @return SimpleForm Form object containing the matching ID. * @access public */ function getFormById($id) { return $this->findForm('getFormById', $id); } /** * General form finder. Will search all the frames or * just the one in focus. * @param string $method Method to use to find in a page. * @param string $attribute Label, name or ID. * @return SimpleForm Form object containing the matching ID. * @access private */ protected function findForm($method, $attribute) { if (is_integer($this->focus)) { return $this->findFormInFrame( $this->frames[$this->focus], $this->focus, $method, $attribute); } for ($i = 0; $i < count($this->frames); $i++) { $form = $this->findFormInFrame( $this->frames[$i], $i, $method, $attribute); if ($form) { return $form; } } $null = null; return $null; } /** * Finds a form in a page using a form finding method. Will * also tag the form with the frame name it belongs in. * @param SimplePage $page Page content of frame. * @param integer $index Internal frame representation. * @param string $method Method to use to find in a page. * @param string $attribute Label, name or ID. * @return SimpleForm Form object containing the matching ID. * @access private */ protected function findFormInFrame($page, $index, $method, $attribute) { $form = $this->frames[$index]->$method($attribute); if (isset($form)) { $form->setDefaultTarget($this->getPublicNameFromIndex($index)); } return $form; } /** * Sets a field on each form in which the field is * available. * @param SimpleSelector $selector Field finder. * @param string $value Value to set field to. * @return boolean True if value is valid. * @access public */ function setField($selector, $value) { if (is_integer($this->focus)) { $this->frames[$this->focus]->setField($selector, $value); } else { for ($i = 0; $i < count($this->frames); $i++) { $this->frames[$i]->setField($selector, $value); } } } /** * Accessor for a form element value within a page. * @param SimpleSelector $selector Field finder. * @return string/boolean A string if the field is * present, false if unchecked * and null if missing. * @access public */ function getField($selector) { for ($i = 0; $i < count($this->frames); $i++) { $value = $this->frames[$i]->getField($selector); if (isset($value)) { return $value; } } return null; } } ?>Swift-4.2.1/test-suite/lib/simpletest/http.php100644 0 0 46013 12000050366 16512 0ustar 0 0 url = $url; } /** * Resource name. * @return SimpleUrl Current url. * @access protected */ function getUrl() { return $this->url; } /** * Creates the first line which is the actual request. * @param string $method HTTP request method, usually GET. * @return string Request line content. * @access protected */ protected function getRequestLine($method) { return $method . ' ' . $this->url->getPath() . $this->url->getEncodedRequest() . ' HTTP/1.0'; } /** * Creates the host part of the request. * @return string Host line content. * @access protected */ protected function getHostLine() { $line = 'Host: ' . $this->url->getHost(); if ($this->url->getPort()) { $line .= ':' . $this->url->getPort(); } return $line; } /** * Opens a socket to the route. * @param string $method HTTP request method, usually GET. * @param integer $timeout Connection timeout. * @return SimpleSocket New socket. * @access public */ function createConnection($method, $timeout) { $default_port = ('https' == $this->url->getScheme()) ? 443 : 80; $socket = $this->createSocket( $this->url->getScheme() ? $this->url->getScheme() : 'http', $this->url->getHost(), $this->url->getPort() ? $this->url->getPort() : $default_port, $timeout); if (! $socket->isError()) { $socket->write($this->getRequestLine($method) . "\r\n"); $socket->write($this->getHostLine() . "\r\n"); $socket->write("Connection: close\r\n"); } return $socket; } /** * Factory for socket. * @param string $scheme Protocol to use. * @param string $host Hostname to connect to. * @param integer $port Remote port. * @param integer $timeout Connection timeout. * @return SimpleSocket/SimpleSecureSocket New socket. * @access protected */ protected function createSocket($scheme, $host, $port, $timeout) { if (in_array($scheme, array('file'))) { return new SimpleFileSocket($this->url); } elseif (in_array($scheme, array('https'))) { return new SimpleSecureSocket($host, $port, $timeout); } else { return new SimpleSocket($host, $port, $timeout); } } } /** * Creates HTTP headers for the end point of * a HTTP request via a proxy server. * @package SimpleTest * @subpackage WebTester */ class SimpleProxyRoute extends SimpleRoute { private $proxy; private $username; private $password; /** * Stashes the proxy address. * @param SimpleUrl $url URL as object. * @param string $proxy Proxy URL. * @param string $username Username for autentication. * @param string $password Password for autentication. * @access public */ function __construct($url, $proxy, $username = false, $password = false) { parent::__construct($url); $this->proxy = $proxy; $this->username = $username; $this->password = $password; } /** * Creates the first line which is the actual request. * @param string $method HTTP request method, usually GET. * @param SimpleUrl $url URL as object. * @return string Request line content. * @access protected */ function getRequestLine($method) { $url = $this->getUrl(); $scheme = $url->getScheme() ? $url->getScheme() : 'http'; $port = $url->getPort() ? ':' . $url->getPort() : ''; return $method . ' ' . $scheme . '://' . $url->getHost() . $port . $url->getPath() . $url->getEncodedRequest() . ' HTTP/1.0'; } /** * Creates the host part of the request. * @param SimpleUrl $url URL as object. * @return string Host line content. * @access protected */ function getHostLine() { $host = 'Host: ' . $this->proxy->getHost(); $port = $this->proxy->getPort() ? $this->proxy->getPort() : 8080; return "$host:$port"; } /** * Opens a socket to the route. * @param string $method HTTP request method, usually GET. * @param integer $timeout Connection timeout. * @return SimpleSocket New socket. * @access public */ function createConnection($method, $timeout) { $socket = $this->createSocket( $this->proxy->getScheme() ? $this->proxy->getScheme() : 'http', $this->proxy->getHost(), $this->proxy->getPort() ? $this->proxy->getPort() : 8080, $timeout); if ($socket->isError()) { return $socket; } $socket->write($this->getRequestLine($method) . "\r\n"); $socket->write($this->getHostLine() . "\r\n"); if ($this->username && $this->password) { $socket->write('Proxy-Authorization: Basic ' . base64_encode($this->username . ':' . $this->password) . "\r\n"); } $socket->write("Connection: close\r\n"); return $socket; } } /** * HTTP request for a web page. Factory for * HttpResponse object. * @package SimpleTest * @subpackage WebTester */ class SimpleHttpRequest { private $route; private $encoding; private $headers; private $cookies; /** * Builds the socket request from the different pieces. * These include proxy information, URL, cookies, headers, * request method and choice of encoding. * @param SimpleRoute $route Request route. * @param SimpleFormEncoding $encoding Content to send with * request. * @access public */ function __construct($route, $encoding) { $this->route = $route; $this->encoding = $encoding; $this->headers = array(); $this->cookies = array(); } /** * Dispatches the content to the route's socket. * @param integer $timeout Connection timeout. * @return SimpleHttpResponse A response which may only have * an error, but hopefully has a * complete web page. * @access public */ function fetch($timeout) { $socket = $this->route->createConnection($this->encoding->getMethod(), $timeout); if (! $socket->isError()) { $this->dispatchRequest($socket, $this->encoding); } return $this->createResponse($socket); } /** * Sends the headers. * @param SimpleSocket $socket Open socket. * @param string $method HTTP request method, * usually GET. * @param SimpleFormEncoding $encoding Content to send with request. * @access private */ protected function dispatchRequest($socket, $encoding) { foreach ($this->headers as $header_line) { $socket->write($header_line . "\r\n"); } if (count($this->cookies) > 0) { $socket->write("Cookie: " . implode(";", $this->cookies) . "\r\n"); } $encoding->writeHeadersTo($socket); $socket->write("\r\n"); $encoding->writeTo($socket); } /** * Adds a header line to the request. * @param string $header_line Text of full header line. * @access public */ function addHeaderLine($header_line) { $this->headers[] = $header_line; } /** * Reads all the relevant cookies from the * cookie jar. * @param SimpleCookieJar $jar Jar to read * @param SimpleUrl $url Url to use for scope. * @access public */ function readCookiesFromJar($jar, $url) { $this->cookies = $jar->selectAsPairs($url); } /** * Wraps the socket in a response parser. * @param SimpleSocket $socket Responding socket. * @return SimpleHttpResponse Parsed response object. * @access protected */ protected function createResponse($socket) { $response = new SimpleHttpResponse( $socket, $this->route->getUrl(), $this->encoding); $socket->close(); return $response; } } /** * Collection of header lines in the response. * @package SimpleTest * @subpackage WebTester */ class SimpleHttpHeaders { private $raw_headers; private $response_code; private $http_version; private $mime_type; private $location; private $cookies; private $authentication; private $realm; /** * Parses the incoming header block. * @param string $headers Header block. * @access public */ function __construct($headers) { $this->raw_headers = $headers; $this->response_code = false; $this->http_version = false; $this->mime_type = ''; $this->location = false; $this->cookies = array(); $this->authentication = false; $this->realm = false; foreach (split("\r\n", $headers) as $header_line) { $this->parseHeaderLine($header_line); } } /** * Accessor for parsed HTTP protocol version. * @return integer HTTP error code. * @access public */ function getHttpVersion() { return $this->http_version; } /** * Accessor for raw header block. * @return string All headers as raw string. * @access public */ function getRaw() { return $this->raw_headers; } /** * Accessor for parsed HTTP error code. * @return integer HTTP error code. * @access public */ function getResponseCode() { return (integer)$this->response_code; } /** * Returns the redirected URL or false if * no redirection. * @return string URL or false for none. * @access public */ function getLocation() { return $this->location; } /** * Test to see if the response is a valid redirect. * @return boolean True if valid redirect. * @access public */ function isRedirect() { return in_array($this->response_code, array(301, 302, 303, 307)) && (boolean)$this->getLocation(); } /** * Test to see if the response is an authentication * challenge. * @return boolean True if challenge. * @access public */ function isChallenge() { return ($this->response_code == 401) && (boolean)$this->authentication && (boolean)$this->realm; } /** * Accessor for MIME type header information. * @return string MIME type. * @access public */ function getMimeType() { return $this->mime_type; } /** * Accessor for authentication type. * @return string Type. * @access public */ function getAuthentication() { return $this->authentication; } /** * Accessor for security realm. * @return string Realm. * @access public */ function getRealm() { return $this->realm; } /** * Writes new cookies to the cookie jar. * @param SimpleCookieJar $jar Jar to write to. * @param SimpleUrl $url Host and path to write under. * @access public */ function writeCookiesToJar($jar, $url) { foreach ($this->cookies as $cookie) { $jar->setCookie( $cookie->getName(), $cookie->getValue(), $url->getHost(), $cookie->getPath(), $cookie->getExpiry()); } } /** * Called on each header line to accumulate the held * data within the class. * @param string $header_line One line of header. * @access protected */ protected function parseHeaderLine($header_line) { if (preg_match('/HTTP\/(\d+\.\d+)\s+(\d+)/i', $header_line, $matches)) { $this->http_version = $matches[1]; $this->response_code = $matches[2]; } if (preg_match('/Content-type:\s*(.*)/i', $header_line, $matches)) { $this->mime_type = trim($matches[1]); } if (preg_match('/Location:\s*(.*)/i', $header_line, $matches)) { $this->location = trim($matches[1]); } if (preg_match('/Set-cookie:(.*)/i', $header_line, $matches)) { $this->cookies[] = $this->parseCookie($matches[1]); } if (preg_match('/WWW-Authenticate:\s+(\S+)\s+realm=\"(.*?)\"/i', $header_line, $matches)) { $this->authentication = $matches[1]; $this->realm = trim($matches[2]); } } /** * Parse the Set-cookie content. * @param string $cookie_line Text after "Set-cookie:" * @return SimpleCookie New cookie object. * @access private */ protected function parseCookie($cookie_line) { $parts = split(";", $cookie_line); $cookie = array(); preg_match('/\s*(.*?)\s*=(.*)/', array_shift($parts), $cookie); foreach ($parts as $part) { if (preg_match('/\s*(.*?)\s*=(.*)/', $part, $matches)) { $cookie[$matches[1]] = trim($matches[2]); } } return new SimpleCookie( $cookie[1], trim($cookie[2]), isset($cookie["path"]) ? $cookie["path"] : "", isset($cookie["expires"]) ? $cookie["expires"] : false); } } /** * Basic HTTP response. * @package SimpleTest * @subpackage WebTester */ class SimpleHttpResponse extends SimpleStickyError { private $url; private $encoding; private $sent; private $content; private $headers; /** * Constructor. Reads and parses the incoming * content and headers. * @param SimpleSocket $socket Network connection to fetch * response text from. * @param SimpleUrl $url Resource name. * @param mixed $encoding Record of content sent. * @access public */ function __construct($socket, $url, $encoding) { parent::__construct(); $this->url = $url; $this->encoding = $encoding; $this->sent = $socket->getSent(); $this->content = false; $raw = $this->readAll($socket); if ($socket->isError()) { $this->setError('Error reading socket [' . $socket->getError() . ']'); return; } $this->parse($raw); } /** * Splits up the headers and the rest of the content. * @param string $raw Content to parse. * @access private */ protected function parse($raw) { if (! $raw) { $this->setError('Nothing fetched'); $this->headers = new SimpleHttpHeaders(''); } elseif ('file' == $this->url->getScheme()) { $this->headers = new SimpleHttpHeaders(''); $this->content = $raw; } elseif (! strstr($raw, "\r\n\r\n")) { $this->setError('Could not split headers from content'); $this->headers = new SimpleHttpHeaders($raw); } else { list($headers, $this->content) = split("\r\n\r\n", $raw, 2); $this->headers = new SimpleHttpHeaders($headers); } } /** * Original request method. * @return string GET, POST or HEAD. * @access public */ function getMethod() { return $this->encoding->getMethod(); } /** * Resource name. * @return SimpleUrl Current url. * @access public */ function getUrl() { return $this->url; } /** * Original request data. * @return mixed Sent content. * @access public */ function getRequestData() { return $this->encoding; } /** * Raw request that was sent down the wire. * @return string Bytes actually sent. * @access public */ function getSent() { return $this->sent; } /** * Accessor for the content after the last * header line. * @return string All content. * @access public */ function getContent() { return $this->content; } /** * Accessor for header block. The response is the * combination of this and the content. * @return SimpleHeaders Wrapped header block. * @access public */ function getHeaders() { return $this->headers; } /** * Accessor for any new cookies. * @return array List of new cookies. * @access public */ function getNewCookies() { return $this->headers->getNewCookies(); } /** * Reads the whole of the socket output into a * single string. * @param SimpleSocket $socket Unread socket. * @return string Raw output if successful * else false. * @access private */ protected function readAll($socket) { $all = ''; while (! $this->isLastPacket($next = $socket->read())) { $all .= $next; } return $all; } /** * Test to see if the packet from the socket is the * last one. * @param string $packet Chunk to interpret. * @return boolean True if empty or EOF. * @access private */ protected function isLastPacket($packet) { if (is_string($packet)) { return $packet === ''; } return ! $packet; } } ?>Swift-4.2.1/test-suite/lib/simpletest/invoker.php100644 0 0 6766 12000050366 17203 0ustar 0 0 test_case = $test_case; } /** * Accessor for test case being run. * @return SimpleTestCase Test case. * @access public */ function getTestCase() { return $this->test_case; } /** * Runs test level set up. Used for changing * the mechanics of base test cases. * @param string $method Test method to call. * @access public */ function before($method) { $this->test_case->before($method); } /** * Invokes a test method and buffered with setUp() * and tearDown() calls. * @param string $method Test method to call. * @access public */ function invoke($method) { $this->test_case->setUp(); $this->test_case->$method(); $this->test_case->tearDown(); } /** * Runs test level clean up. Used for changing * the mechanics of base test cases. * @param string $method Test method to call. * @access public */ function after($method) { $this->test_case->after($method); } } /** * Do nothing decorator. Just passes the invocation * straight through. * @package SimpleTest * @subpackage UnitTester */ class SimpleInvokerDecorator { private $invoker; /** * Stores the invoker to wrap. * @param SimpleInvoker $invoker Test method runner. */ function __construct($invoker) { $this->invoker = $invoker; } /** * Accessor for test case being run. * @return SimpleTestCase Test case. * @access public */ function getTestCase() { return $this->invoker->getTestCase(); } /** * Runs test level set up. Used for changing * the mechanics of base test cases. * @param string $method Test method to call. * @access public */ function before($method) { $this->invoker->before($method); } /** * Invokes a test method and buffered with setUp() * and tearDown() calls. * @param string $method Test method to call. * @access public */ function invoke($method) { $this->invoker->invoke($method); } /** * Runs test level clean up. Used for changing * the mechanics of base test cases. * @param string $method Test method to call. * @access public */ function after($method) { $this->invoker->after($method); } } ?>Swift-4.2.1/test-suite/lib/simpletest/mock_objects.php100644 0 0 164317 12000050366 20225 0ustar 0 0 expected = $expected; } /** * Tests the assertion. True if correct. * @param array $parameters Comparison values. * @return boolean True if correct. * @access public */ function test($parameters) { if (! is_array($this->expected)) { return true; } if (count($this->expected) != count($parameters)) { return false; } for ($i = 0; $i < count($this->expected); $i++) { if (! $this->testParameter($parameters[$i], $this->expected[$i])) { return false; } } return true; } /** * Tests an individual parameter. * @param mixed $parameter Value to test. * @param mixed $expected Comparison value. * @return boolean True if expectation * fulfilled. * @access private */ protected function testParameter($parameter, $expected) { $comparison = $this->coerceToExpectation($expected); return $comparison->test($parameter); } /** * Returns a human readable test message. * @param array $comparison Incoming parameter list. * @return string Description of success * or failure. * @access public */ function testMessage($parameters) { if ($this->test($parameters)) { return "Expectation of " . count($this->expected) . " arguments of [" . $this->renderArguments($this->expected) . "] is correct"; } else { return $this->describeDifference($this->expected, $parameters); } } /** * Message to display if expectation differs from * the parameters actually received. * @param array $expected Expected parameters as list. * @param array $parameters Actual parameters received. * @return string Description of difference. * @access private */ protected function describeDifference($expected, $parameters) { if (count($expected) != count($parameters)) { return "Expected " . count($expected) . " arguments of [" . $this->renderArguments($expected) . "] but got " . count($parameters) . " arguments of [" . $this->renderArguments($parameters) . "]"; } $messages = array(); for ($i = 0; $i < count($expected); $i++) { $comparison = $this->coerceToExpectation($expected[$i]); if (! $comparison->test($parameters[$i])) { $messages[] = "parameter " . ($i + 1) . " with [" . $comparison->overlayMessage($parameters[$i], $this->getDumper()) . "]"; } } return "Parameter expectation differs at " . implode(" and ", $messages); } /** * Creates an identical expectation if the * object/value is not already some type * of expectation. * @param mixed $expected Expected value. * @return SimpleExpectation Expectation object. * @access private */ protected function coerceToExpectation($expected) { if (SimpleExpectation::isExpectation($expected)) { return $expected; } return new IdenticalExpectation($expected); } /** * Renders the argument list as a string for * messages. * @param array $args Incoming arguments. * @return string Simple description of type and value. * @access private */ protected function renderArguments($args) { $descriptions = array(); if (is_array($args)) { foreach ($args as $arg) { $dumper = new SimpleDumper(); $descriptions[] = $dumper->describeValue($arg); } } return implode(', ', $descriptions); } } /** * Confirms that the number of calls on a method is as expected. * @package SimpleTest * @subpackage MockObjects */ class CallCountExpectation extends SimpleExpectation { private $method; private $count; /** * Stashes the method and expected count for later * reporting. * @param string $method Name of method to confirm against. * @param integer $count Expected number of calls. * @param string $message Custom error message. */ function __construct($method, $count, $message = '%s') { $this->method = $method; $this->count = $count; parent::__construct($message); } /** * Tests the assertion. True if correct. * @param integer $compare Measured call count. * @return boolean True if expected. * @access public */ function test($compare) { return ($this->count == $compare); } /** * Reports the comparison. * @param integer $compare Measured call count. * @return string Message to show. * @access public */ function testMessage($compare) { return 'Expected call count for [' . $this->method . '] was [' . $this->count . '] got [' . $compare . ']'; } } /** * Confirms that the number of calls on a method is as expected. * @package SimpleTest * @subpackage MockObjects */ class MinimumCallCountExpectation extends SimpleExpectation { private $method; private $count; /** * Stashes the method and expected count for later * reporting. * @param string $method Name of method to confirm against. * @param integer $count Minimum number of calls. * @param string $message Custom error message. */ function __construct($method, $count, $message = '%s') { $this->method = $method; $this->count = $count; parent::__construct($message); } /** * Tests the assertion. True if correct. * @param integer $compare Measured call count. * @return boolean True if enough. * @access public */ function test($compare) { return ($this->count <= $compare); } /** * Reports the comparison. * @param integer $compare Measured call count. * @return string Message to show. * @access public */ function testMessage($compare) { return 'Minimum call count for [' . $this->method . '] was [' . $this->count . '] got [' . $compare . ']'; } } /** * Confirms that the number of calls on a method is as expected. * @package SimpleTest * @subpackage MockObjects */ class MaximumCallCountExpectation extends SimpleExpectation { private $method; private $count; /** * Stashes the method and expected count for later * reporting. * @param string $method Name of method to confirm against. * @param integer $count Minimum number of calls. * @param string $message Custom error message. */ function __construct($method, $count, $message = '%s') { $this->method = $method; $this->count = $count; parent::__construct($message); } /** * Tests the assertion. True if correct. * @param integer $compare Measured call count. * @return boolean True if not over. * @access public */ function test($compare) { return ($this->count >= $compare); } /** * Reports the comparison. * @param integer $compare Measured call count. * @return string Message to show. * @access public */ function testMessage($compare) { return 'Maximum call count for [' . $this->method . '] was [' . $this->count . '] got [' . $compare . ']'; } } /** * Retrieves method actions by searching the * parameter lists until an expected match is found. * @package SimpleTest * @subpackage MockObjects */ class SimpleSignatureMap { private $map; /** * Creates an empty call map. * @access public */ function __construct() { $this->map = array(); } /** * Stashes a reference against a method call. * @param array $parameters Array of arguments (including wildcards). * @param mixed $action Reference placed in the map. * @access public */ function add($parameters, $action) { $place = count($this->map); $this->map[$place] = array(); $this->map[$place]['params'] = new ParametersExpectation($parameters); $this->map[$place]['content'] = $action; } /** * Searches the call list for a matching parameter * set. Returned by reference. * @param array $parameters Parameters to search by * without wildcards. * @return object Object held in the first matching * slot, otherwise null. * @access public */ function &findFirstAction($parameters) { $slot = $this->findFirstSlot($parameters); if (isset($slot) && isset($slot['content'])) { return $slot['content']; } $null = null; return $null; } /** * Searches the call list for a matching parameter * set. True if successful. * @param array $parameters Parameters to search by * without wildcards. * @return boolean True if a match is present. * @access public */ function isMatch($parameters) { return ($this->findFirstSlot($parameters) != null); } /** * Compares the incoming parameters with the * internal expectation. Uses the incoming $test * to dispatch the test message. * @param SimpleTestCase $test Test to dispatch to. * @param array $parameters The actual calling arguments. * @param string $message The message to overlay. * @access public */ function test($test, $parameters, $message) { } /** * Searches the map for a matching item. * @param array $parameters Parameters to search by * without wildcards. * @return array Reference to slot or null. * @access private */ function &findFirstSlot($parameters) { $count = count($this->map); for ($i = 0; $i < $count; $i++) { if ($this->map[$i]["params"]->test($parameters)) { return $this->map[$i]; } } $null = null; return $null; } } /** * Allows setting of actions against call signatures either * at a specific time, or always. Specific time settings * trump lasting ones, otherwise the most recently added * will mask an earlier match. * @package SimpleTest * @subpackage MockObjects */ class SimpleCallSchedule { private $wildcard = MOCK_ANYTHING; private $always; private $at; /** * Sets up an empty response schedule. * Creates an empty call map. */ function __construct() { $this->always = array(); $this->at = array(); } /** * Stores an action against a signature that * will always fire unless masked by a time * specific one. * @param string $method Method name. * @param array $args Calling parameters. * @param SimpleAction $action Actually simpleByValue, etc. * @access public */ function register($method, $args, $action) { $args = $this->replaceWildcards($args); $method = strtolower($method); if (! isset($this->always[$method])) { $this->always[$method] = new SimpleSignatureMap(); } $this->always[$method]->add($args, $action); } /** * Stores an action against a signature that * will fire at a specific time in the future. * @param integer $step delay of calls to this method, * 0 is next. * @param string $method Method name. * @param array $args Calling parameters. * @param SimpleAction $action Actually SimpleByValue, etc. * @access public */ function registerAt($step, $method, $args, $action) { $args = $this->replaceWildcards($args); $method = strtolower($method); if (! isset($this->at[$method])) { $this->at[$method] = array(); } if (! isset($this->at[$method][$step])) { $this->at[$method][$step] = new SimpleSignatureMap(); } $this->at[$method][$step]->add($args, $action); } /** * Sets up an expectation on the argument list. * @param string $method Method to test. * @param array $args Bare arguments or list of * expectation objects. * @param string $message Failure message. */ function expectArguments($method, $args, $message) { $args = $this->replaceWildcards($args); $message .= Mock::getExpectationLine(); $this->expected_args[strtolower($method)] = new ParametersExpectation($args, $message); } /** * Actually carry out the action stored previously, * if the parameters match. * @param integer $step Time of call. * @param string $method Method name. * @param array $args The parameters making up the * rest of the call. * @return mixed The result of the action. * @access public. */ function &respond($step, $method, $args) { $method = strtolower($method); if (isset($this->at[$method][$step])) { if ($this->at[$method][$step]->isMatch($args)) { $action = $this->at[$method][$step]->findFirstAction($args); if (isset($action)) { return $action->act(); } } } if (isset($this->always[$method])) { $action = $this->always[$method]->findFirstAction($args); if (isset($action)) { return $action->act(); } } $null = null; return $null; } /** * Replaces wildcard matches with wildcard * expectations in the argument list. * @param array $args Raw argument list. * @return array Argument list with * expectations. * @access private */ protected function replaceWildcards($args) { if ($args === false) { return false; } for ($i = 0; $i < count($args); $i++) { if ($args[$i] === $this->wildcard) { $args[$i] = new AnythingExpectation(); } } return $args; } } /** * A type of SimpleMethodAction. * Stashes a value for returning later. Follows usual * PHP5 semantics of objects being returned by reference. * @package SimpleTest * @subpackage MockObjects */ class SimpleReturn { private $value; /** * Stashes it for later. * @param mixed $value You need to clone objects * if you want copy semantics * for these. * @access public */ function __construct($value) { $this->value = $value; } /** * Returns the value stored earlier. * @return mixed Whatever was stashed. * @access public */ function act() { return $this->value; } } /** * A type of SimpleMethodAction. * Stashes a reference for returning later. * @package SimpleTest * @subpackage MockObjects */ class SimpleByReference { private $reference; /** * Stashes it for later. * @param mixed $reference Actual PHP4 style reference. * @access public */ function __construct(&$reference) { $this->reference = &$reference; } /** * Returns the reference stored earlier. * @return mixed Whatever was stashed. * @access public */ function &act() { return $this->reference; } } /** * A type of SimpleMethodAction. * Stashes a value for returning later. * @package SimpleTest * @subpackage MockObjects */ class SimpleByValue { private $value; /** * Stashes it for later. * @param mixed $value You need to clone objects * if you want copy semantics * for these. * @access public */ function __construct($value) { $this->value = $value; } /** * Returns the value stored earlier. * @return mixed Whatever was stashed. * @access public */ function &act() { $dummy = $this->value; return $dummy; } } /** * A type of SimpleMethodAction. * Stashes an exception for throwing later. * @package SimpleTest * @subpackage MockObjects */ class SimpleThrower { private $exception; /** * Stashes it for later. * @param Exception $exception The exception object to throw. * @access public */ function __construct($exception) { $this->exception = $exception; } /** * Throws the exceptins stashed earlier. * @access public */ function act() { throw $this->exception; } } /** * A type of SimpleMethodAction. * Stashes an error for emitting later. * @package SimpleTest * @subpackage MockObjects */ class SimpleErrorThrower { private $error; private $severity; /** * Stashes an error to throw later. * @param string $error Error message. * @param integer $severity PHP error constant, e.g E_USER_ERROR. * @access public */ function __construct($error, $severity) { $this->error = $error; $this->severity = $severity; } /** * Triggers the stashed error. * @access public */ function &act() { trigger_error($this->error, $this->severity); $null = null; return $null; } } /** * A base class or delegate that extends an * empty collection of methods that can have their * return values set and expectations made of the * calls upon them. The mock will assert the * expectations against it's attached test case in * addition to the server stub behaviour or returning * preprogrammed responses. * @package SimpleTest * @subpackage MockObjects */ class SimpleMock { private $actions; private $expectations; private $wildcard = MOCK_ANYTHING; private $is_strict = true; private $call_counts; private $expected_counts; private $max_counts; private $expected_args; private $expected_args_at; /** * Creates an empty action list and expectation list. * All call counts are set to zero. * @access public */ function SimpleMock() { $this->actions = new SimpleCallSchedule(); $this->expectations = new SimpleCallSchedule(); $this->call_counts = array(); $this->expected_counts = array(); $this->max_counts = array(); $this->expected_args = array(); $this->expected_args_at = array(); $this->getCurrentTestCase()->tell($this); } /** * Disables a name check when setting expectations. * This hack is needed for the partial mocks. * @access public */ function disableExpectationNameChecks() { $this->is_strict = false; } /** * Finds currently running test. * @return SimpeTestCase Current test case. * @access protected */ protected function getCurrentTestCase() { return SimpleTest::getContext()->getTest(); } /** * Die if bad arguments array is passed. * @param mixed $args The arguments value to be checked. * @param string $task Description of task attempt. * @return boolean Valid arguments * @access private */ protected function checkArgumentsIsArray($args, $task) { if (! is_array($args)) { trigger_error( "Cannot $task as \$args parameter is not an array", E_USER_ERROR); } } /** * Triggers a PHP error if the method is not part * of this object. * @param string $method Name of method. * @param string $task Description of task attempt. * @access protected */ protected function dieOnNoMethod($method, $task) { if ($this->is_strict && ! method_exists($this, $method)) { trigger_error( "Cannot $task as no ${method}() in class " . get_class($this), E_USER_ERROR); } } /** * Replaces wildcard matches with wildcard * expectations in the argument list. * @param array $args Raw argument list. * @return array Argument list with * expectations. * @access private */ function replaceWildcards($args) { if ($args === false) { return false; } for ($i = 0; $i < count($args); $i++) { if ($args[$i] === $this->wildcard) { $args[$i] = new AnythingExpectation(); } } return $args; } /** * Adds one to the call count of a method. * @param string $method Method called. * @param array $args Arguments as an array. * @access protected */ protected function addCall($method, $args) { if (! isset($this->call_counts[$method])) { $this->call_counts[$method] = 0; } $this->call_counts[$method]++; } /** * Fetches the call count of a method so far. * @param string $method Method name called. * @return integer Number of calls so far. * @access public */ function getCallCount($method) { $this->dieOnNoMethod($method, "get call count"); $method = strtolower($method); if (! isset($this->call_counts[$method])) { return 0; } return $this->call_counts[$method]; } /** * Sets a return for a parameter list that will * be passed on by all calls to this method that match. * @param string $method Method name. * @param mixed $value Result of call by value/handle. * @param array $args List of parameters to match * including wildcards. * @access public */ function returns($method, $value, $args = false) { $this->dieOnNoMethod($method, "set return"); $this->actions->register($method, $args, new SimpleReturn($value)); } /** * Sets a return for a parameter list that will * be passed only when the required call count * is reached. * @param integer $timing Number of calls in the future * to which the result applies. If * not set then all calls will return * the value. * @param string $method Method name. * @param mixed $value Result of call passed. * @param array $args List of parameters to match * including wildcards. * @access public */ function returnsAt($timing, $method, $value, $args = false) { $this->dieOnNoMethod($method, "set return value sequence"); $this->actions->registerAt($timing, $method, $args, new SimpleReturn($value)); } /** * Sets a return for a parameter list that will * be passed by value for all calls to this method. * @param string $method Method name. * @param mixed $value Result of call passed by value. * @param array $args List of parameters to match * including wildcards. * @access public */ function setReturnValue($method, $value, $args = false) { $this->dieOnNoMethod($method, "set return value"); $this->actions->register($method, $args, new SimpleByValue($value)); } /** * Sets a return for a parameter list that will * be passed by value only when the required call count * is reached. * @param integer $timing Number of calls in the future * to which the result applies. If * not set then all calls will return * the value. * @param string $method Method name. * @param mixed $value Result of call passed by value. * @param array $args List of parameters to match * including wildcards. * @access public */ function setReturnValueAt($timing, $method, $value, $args = false) { $this->dieOnNoMethod($method, "set return value sequence"); $this->actions->registerAt($timing, $method, $args, new SimpleByValue($value)); } /** * Sets a return for a parameter list that will * be passed by reference for all calls. * @param string $method Method name. * @param mixed $reference Result of the call will be this object. * @param array $args List of parameters to match * including wildcards. * @access public */ function setReturnReference($method, &$reference, $args = false) { $this->dieOnNoMethod($method, "set return reference"); $this->actions->register($method, $args, new SimpleByReference($reference)); } /** * Sets a return for a parameter list that will * be passed by value only when the required call count * is reached. * @param integer $timing Number of calls in the future * to which the result applies. If * not set then all calls will return * the value. * @param string $method Method name. * @param mixed $reference Result of the call will be this object. * @param array $args List of parameters to match * including wildcards. * @access public */ function setReturnReferenceAt($timing, $method, &$reference, $args = false) { $this->dieOnNoMethod($method, "set return reference sequence"); $this->actions->registerAt($timing, $method, $args, new SimpleByReference($reference)); } /** * Sets up an expected call with a set of * expected parameters in that call. All * calls will be compared to these expectations * regardless of when the call is made. * @param string $method Method call to test. * @param array $args Expected parameters for the call * including wildcards. * @param string $message Overridden message. * @access public */ function expect($method, $args, $message = '%s') { $this->dieOnNoMethod($method, 'set expected arguments'); $this->checkArgumentsIsArray($args, 'set expected arguments'); $this->expectations->expectArguments($method, $args, $message); $args = $this->replaceWildcards($args); $message .= Mock::getExpectationLine(); $this->expected_args[strtolower($method)] = new ParametersExpectation($args, $message); } /** * Sets up an expected call with a set of * expected parameters in that call. The * expected call count will be adjusted if it * is set too low to reach this call. * @param integer $timing Number of calls in the future at * which to test. Next call is 0. * @param string $method Method call to test. * @param array $args Expected parameters for the call * including wildcards. * @param string $message Overridden message. * @access public */ function expectAt($timing, $method, $args, $message = '%s') { $this->dieOnNoMethod($method, 'set expected arguments at time'); $this->checkArgumentsIsArray($args, 'set expected arguments at time'); $args = $this->replaceWildcards($args); if (! isset($this->expected_args_at[$timing])) { $this->expected_args_at[$timing] = array(); } $method = strtolower($method); $message .= Mock::getExpectationLine(); $this->expected_args_at[$timing][$method] = new ParametersExpectation($args, $message); } /** * Sets an expectation for the number of times * a method will be called. The tally method * is used to check this. * @param string $method Method call to test. * @param integer $count Number of times it should * have been called at tally. * @param string $message Overridden message. * @access public */ function expectCallCount($method, $count, $message = '%s') { $this->dieOnNoMethod($method, 'set expected call count'); $message .= Mock::getExpectationLine(); $this->expected_counts[strtolower($method)] = new CallCountExpectation($method, $count, $message); } /** * Sets the number of times a method may be called * before a test failure is triggered. * @param string $method Method call to test. * @param integer $count Most number of times it should * have been called. * @param string $message Overridden message. * @access public */ function expectMaximumCallCount($method, $count, $message = '%s') { $this->dieOnNoMethod($method, 'set maximum call count'); $message .= Mock::getExpectationLine(); $this->max_counts[strtolower($method)] = new MaximumCallCountExpectation($method, $count, $message); } /** * Sets the number of times to call a method to prevent * a failure on the tally. * @param string $method Method call to test. * @param integer $count Least number of times it should * have been called. * @param string $message Overridden message. * @access public */ function expectMinimumCallCount($method, $count, $message = '%s') { $this->dieOnNoMethod($method, 'set minimum call count'); $message .= Mock::getExpectationLine(); $this->expected_counts[strtolower($method)] = new MinimumCallCountExpectation($method, $count, $message); } /** * Convenience method for barring a method * call. * @param string $method Method call to ban. * @param string $message Overridden message. * @access public */ function expectNever($method, $message = '%s') { $this->expectMaximumCallCount($method, 0, $message); } /** * Convenience method for a single method * call. * @param string $method Method call to track. * @param array $args Expected argument list or * false for any arguments. * @param string $message Overridden message. * @access public */ function expectOnce($method, $args = false, $message = '%s') { $this->expectCallCount($method, 1, $message); if ($args !== false) { $this->expect($method, $args, $message); } } /** * Convenience method for requiring a method * call. * @param string $method Method call to track. * @param array $args Expected argument list or * false for any arguments. * @param string $message Overridden message. * @access public */ function expectAtLeastOnce($method, $args = false, $message = '%s') { $this->expectMinimumCallCount($method, 1, $message); if ($args !== false) { $this->expect($method, $args, $message); } } /** * Sets up a trigger to throw an exception upon the * method call. * @param string $method Method name to throw on. */ function throwOn($method, $exception = false, $args = false) { $this->dieOnNoMethod($method, "throw on"); $this->actions->register($method, $args, new SimpleThrower($exception ? $exception : new Exception())); } /** * Sets up a trigger to throw an exception upon the * method call. */ function throwAt($timing, $method, $exception = false, $args = false) { $this->dieOnNoMethod($method, "throw at"); $this->actions->registerAt($timing, $method, $args, new SimpleThrower($exception ? $exception : new Exception())); } /** * Sets up a trigger to throw an error upon the * method call. */ function errorOn($method, $error = 'A mock error', $args = false, $severity = E_USER_ERROR) { $this->dieOnNoMethod($method, "error on"); $this->actions->register($method, $args, new SimpleErrorThrower($error, $severity)); } /** * Sets up a trigger to throw an error upon the * method call. */ function errorAt($timing, $method, $error = 'A mock error', $args = false, $severity = E_USER_ERROR) { $this->dieOnNoMethod($method, "error at"); $this->actions->registerAt($timing, $method, $args, new SimpleErrorThrower($error, $severity)); } /** * Receives event from unit test that the current * test method has finished. Totals up the call * counts and triggers a test assertion if a test * is present for expected call counts. * @param string $test_method Current method name. * @param SimpleTestCase $test Test to send message to. * @access public */ function atTestEnd($test_method, &$test) { foreach ($this->expected_counts as $method => $expectation) { $test->assert($expectation, $this->getCallCount($method)); } foreach ($this->max_counts as $method => $expectation) { if ($expectation->test($this->getCallCount($method))) { $test->assert($expectation, $this->getCallCount($method)); } } } /** * Returns the expected value for the method name * and checks expectations. Will generate any * test assertions as a result of expectations * if there is a test present. * @param string $method Name of method to simulate. * @param array $args Arguments as an array. * @return mixed Stored return. * @access private */ function &invoke($method, $args) { $method = strtolower($method); $step = $this->getCallCount($method); $this->addCall($method, $args); $this->checkExpectations($method, $args, $step); $was = $this->disableEStrict(); try { $result = &$this->emulateCall($method, $args, $step); } catch (Exception $e) { $this->restoreEStrict($was); throw $e; } $this->restoreEStrict($was); return $result; } /** * Finds the return value matching the incoming * arguments. If there is no matching value found * then an error is triggered. * @param string $method Method name. * @param array $args Calling arguments. * @param integer $step Current position in the * call history. * @return mixed Stored return or other action. * @access protected */ protected function &emulateCall($method, $args, $step) { return $this->actions->respond($step, $method, $args); } /** * Tests the arguments against expectations. * @param string $method Method to check. * @param array $args Argument list to match. * @param integer $timing The position of this call * in the call history. * @access private */ protected function checkExpectations($method, $args, $timing) { $test = $this->getCurrentTestCase(); if (isset($this->max_counts[$method])) { if (! $this->max_counts[$method]->test($timing + 1)) { $test->assert($this->max_counts[$method], $timing + 1); } } if (isset($this->expected_args_at[$timing][$method])) { $test->assert( $this->expected_args_at[$timing][$method], $args, "Mock method [$method] at [$timing] -> %s"); } elseif (isset($this->expected_args[$method])) { $test->assert( $this->expected_args[$method], $args, "Mock method [$method] -> %s"); } } private function disableEStrict() { $was = error_reporting(); error_reporting($was & ~E_STRICT); return $was; } private function restoreEStrict($was) { error_reporting($was); } } /** * Static methods only service class for code generation of * mock objects. * @package SimpleTest * @subpackage MockObjects */ class Mock { /** * Factory for mock object classes. * @access public */ function __construct() { trigger_error('Mock factory methods are static.'); } /** * Clones a class' interface and creates a mock version * that can have return values and expectations set. * @param string $class Class to clone. * @param string $mock_class New class name. Default is * the old name with "Mock" * prepended. * @param array $methods Additional methods to add beyond * those in the cloned class. Use this * to emulate the dynamic addition of * methods in the cloned class or when * the class hasn't been written yet.sta * @access public */ static function generate($class, $mock_class = false, $methods = false) { $generator = new MockGenerator($class, $mock_class); return @$generator->generateSubclass($methods); } /** * Generates a version of a class with selected * methods mocked only. Inherits the old class * and chains the mock methods of an aggregated * mock object. * @param string $class Class to clone. * @param string $mock_class New class name. * @param array $methods Methods to be overridden * with mock versions. * @access public */ static function generatePartial($class, $mock_class, $methods) { $generator = new MockGenerator($class, $mock_class); return @$generator->generatePartial($methods); } /** * Uses a stack trace to find the line of an assertion. * @access public */ static function getExpectationLine() { $trace = new SimpleStackTrace(array('expect')); return $trace->traceMethod(); } } /** * Service class for code generation of mock objects. * @package SimpleTest * @subpackage MockObjects */ class MockGenerator { private $class; private $mock_class; private $mock_base; private $reflection; /** * Builds initial reflection object. * @param string $class Class to be mocked. * @param string $mock_class New class with identical interface, * but no behaviour. */ function __construct($class, $mock_class) { $this->class = $class; $this->mock_class = $mock_class; if (! $this->mock_class) { $this->mock_class = 'Mock' . $this->class; } $this->mock_base = SimpleTest::getMockBaseClass(); $this->reflection = new SimpleReflection($this->class); } /** * Clones a class' interface and creates a mock version * that can have return values and expectations set. * @param array $methods Additional methods to add beyond * those in th cloned class. Use this * to emulate the dynamic addition of * methods in the cloned class or when * the class hasn't been written yet. * @access public */ function generate($methods) { if (! $this->reflection->classOrInterfaceExists()) { return false; } $mock_reflection = new SimpleReflection($this->mock_class); if ($mock_reflection->classExistsSansAutoload()) { return false; } $code = $this->createClassCode($methods ? $methods : array()); return eval("$code return \$code;"); } /** * Subclasses a class and overrides every method with a mock one * that can have return values and expectations set. Chains * to an aggregated SimpleMock. * @param array $methods Additional methods to add beyond * those in the cloned class. Use this * to emulate the dynamic addition of * methods in the cloned class or when * the class hasn't been written yet. * @access public */ function generateSubclass($methods) { if (! $this->reflection->classOrInterfaceExists()) { return false; } $mock_reflection = new SimpleReflection($this->mock_class); if ($mock_reflection->classExistsSansAutoload()) { return false; } if ($this->reflection->isInterface() || $this->reflection->hasFinal()) { $code = $this->createClassCode($methods ? $methods : array()); return eval("$code return \$code;"); } else { $code = $this->createSubclassCode($methods ? $methods : array()); return eval("$code return \$code;"); } } /** * Generates a version of a class with selected * methods mocked only. Inherits the old class * and chains the mock methods of an aggregated * mock object. * @param array $methods Methods to be overridden * with mock versions. * @access public */ function generatePartial($methods) { if (! $this->reflection->classExists($this->class)) { return false; } $mock_reflection = new SimpleReflection($this->mock_class); if ($mock_reflection->classExistsSansAutoload()) { trigger_error('Partial mock class [' . $this->mock_class . '] already exists'); return false; } $code = $this->extendClassCode($methods); return eval("$code return \$code;"); } /** * The new mock class code as a string. * @param array $methods Additional methods. * @return string Code for new mock class. * @access private */ protected function createClassCode($methods) { $implements = ''; $interfaces = $this->reflection->getInterfaces(); if (function_exists('spl_classes')) { $interfaces = array_diff($interfaces, array('Traversable')); } if (count($interfaces) > 0) { $implements = 'implements ' . implode(', ', $interfaces); } $code = "class " . $this->mock_class . " extends " . $this->mock_base . " $implements {\n"; $code .= " function " . $this->mock_class . "() {\n"; $code .= " \$this->" . $this->mock_base . "();\n"; $code .= " }\n"; if (in_array('__construct', $this->reflection->getMethods())) { $code .= " function __construct() {\n"; $code .= " \$this->" . $this->mock_base . "();\n"; $code .= " }\n"; } $code .= $this->createHandlerCode($methods); $code .= "}\n"; return $code; } /** * The new mock class code as a string. The mock will * be a subclass of the original mocked class. * @param array $methods Additional methods. * @return string Code for new mock class. * @access private */ protected function createSubclassCode($methods) { $code = "class " . $this->mock_class . " extends " . $this->class . " {\n"; $code .= " public \$mock;\n"; $code .= $this->addMethodList(array_merge($methods, $this->reflection->getMethods())); $code .= "\n"; $code .= " function " . $this->mock_class . "() {\n"; $code .= " \$this->mock = new " . $this->mock_base . "();\n"; $code .= " \$this->mock->disableExpectationNameChecks();\n"; $code .= " }\n"; $code .= $this->chainMockReturns(); $code .= $this->chainMockExpectations(); $code .= $this->chainThrowMethods(); $code .= $this->overrideMethods($this->reflection->getMethods()); $code .= $this->createNewMethodCode($methods); $code .= "}\n"; return $code; } /** * The extension class code as a string. The class * composites a mock object and chains mocked methods * to it. * @param array $methods Mocked methods. * @return string Code for a new class. * @access private */ protected function extendClassCode($methods) { $code = "class " . $this->mock_class . " extends " . $this->class . " {\n"; $code .= " protected \$mock;\n"; $code .= $this->addMethodList($methods); $code .= "\n"; $code .= " function " . $this->mock_class . "() {\n"; $code .= " \$this->mock = new " . $this->mock_base . "();\n"; $code .= " \$this->mock->disableExpectationNameChecks();\n"; $code .= " }\n"; $code .= $this->chainMockReturns(); $code .= $this->chainMockExpectations(); $code .= $this->chainThrowMethods(); $code .= $this->overrideMethods($methods); $code .= "}\n"; return $code; } /** * Creates code within a class to generate replaced * methods. All methods call the invoke() handler * with the method name and the arguments in an * array. * @param array $methods Additional methods. * @access private */ protected function createHandlerCode($methods) { $code = ''; $methods = array_merge($methods, $this->reflection->getMethods()); foreach ($methods as $method) { if ($this->isConstructor($method)) { continue; } $mock_reflection = new SimpleReflection($this->mock_base); if (in_array($method, $mock_reflection->getMethods())) { continue; } $code .= " " . $this->reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; } /** * Creates code within a class to generate a new * methods. All methods call the invoke() handler * on the internal mock with the method name and * the arguments in an array. * @param array $methods Additional methods. * @access private */ protected function createNewMethodCode($methods) { $code = ''; foreach ($methods as $method) { if ($this->isConstructor($method)) { continue; } $mock_reflection = new SimpleReflection($this->mock_base); if (in_array($method, $mock_reflection->getMethods())) { continue; } $code .= " " . $this->reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->mock->invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; } /** * Tests to see if a special PHP method is about to * be stubbed by mistake. * @param string $method Method name. * @return boolean True if special. * @access private */ protected function isConstructor($method) { return in_array( strtolower($method), array('__construct', '__destruct')); } /** * Creates a list of mocked methods for error checking. * @param array $methods Mocked methods. * @return string Code for a method list. * @access private */ protected function addMethodList($methods) { return " protected \$mocked_methods = array('" . implode("', '", array_map('strtolower', $methods)) . "');\n"; } /** * Creates code to abandon the expectation if not mocked. * @param string $alias Parameter name of method name. * @return string Code for bail out. * @access private */ protected function bailOutIfNotMocked($alias) { $code = " if (! in_array(strtolower($alias), \$this->mocked_methods)) {\n"; $code .= " trigger_error(\"Method [$alias] is not mocked\");\n"; $code .= " \$null = null;\n"; $code .= " return \$null;\n"; $code .= " }\n"; return $code; } /** * Creates source code for chaining to the composited * mock object. * @return string Code for mock set up. * @access private */ protected function chainMockReturns() { $code = " function returns(\$method, \$value, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->returns(\$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function returnsAt(\$timing, \$method, \$value, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->returnsAt(\$timing, \$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function setReturnValue(\$method, \$value, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->setReturnValue(\$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function setReturnValueAt(\$timing, \$method, \$value, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->setReturnValueAt(\$timing, \$method, \$value, \$args);\n"; $code .= " }\n"; $code .= " function setReturnReference(\$method, &\$ref, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->setReturnReference(\$method, \$ref, \$args);\n"; $code .= " }\n"; $code .= " function setReturnReferenceAt(\$timing, \$method, &\$ref, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->setReturnReferenceAt(\$timing, \$method, \$ref, \$args);\n"; $code .= " }\n"; return $code; } /** * Creates source code for chaining to an aggregated * mock object. * @return string Code for expectations. * @access private */ protected function chainMockExpectations() { $code = " function expect(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expect(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectAt(\$timing, \$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectAt(\$timing, \$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectCallCount(\$method, \$count) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectMaximumCallCount(\$method, \$count, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectMaximumCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectMinimumCallCount(\$method, \$count, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectMinimumCallCount(\$method, \$count, \$msg = '%s');\n"; $code .= " }\n"; $code .= " function expectNever(\$method) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectNever(\$method);\n"; $code .= " }\n"; $code .= " function expectOnce(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectOnce(\$method, \$args, \$msg);\n"; $code .= " }\n"; $code .= " function expectAtLeastOnce(\$method, \$args = false, \$msg = '%s') {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->expectAtLeastOnce(\$method, \$args, \$msg);\n"; $code .= " }\n"; return $code; } /** * Adds code for chaining the throw methods. * @return string Code for chains. * @access private */ protected function chainThrowMethods() { $code = " function throwOn(\$method, \$exception = false, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->throwOn(\$method, \$exception, \$args);\n"; $code .= " }\n"; $code .= " function throwAt(\$timing, \$method, \$exception = false, \$args = false) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->throwAt(\$timing, \$method, \$exception, \$args);\n"; $code .= " }\n"; $code .= " function errorOn(\$method, \$error = 'A mock error', \$args = false, \$severity = E_USER_ERROR) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->errorOn(\$method, \$error, \$args, \$severity);\n"; $code .= " }\n"; $code .= " function errorAt(\$timing, \$method, \$error = 'A mock error', \$args = false, \$severity = E_USER_ERROR) {\n"; $code .= $this->bailOutIfNotMocked("\$method"); $code .= " \$this->mock->errorAt(\$timing, \$method, \$error, \$args, \$severity);\n"; $code .= " }\n"; return $code; } /** * Creates source code to override a list of methods * with mock versions. * @param array $methods Methods to be overridden * with mock versions. * @return string Code for overridden chains. * @access private */ protected function overrideMethods($methods) { $code = ""; foreach ($methods as $method) { if ($this->isConstructor($method)) { continue; } $code .= " " . $this->reflection->getSignature($method) . " {\n"; $code .= " \$args = func_get_args();\n"; $code .= " \$result = &\$this->mock->invoke(\"$method\", \$args);\n"; $code .= " return \$result;\n"; $code .= " }\n"; } return $code; } } ?>Swift-4.2.1/test-suite/lib/simpletest/page.php100644 0 0 70632 12000050366 16453 0ustar 0 0 'SimpleAnchorTag', 'title' => 'SimpleTitleTag', 'base' => 'SimpleBaseTag', 'button' => 'SimpleButtonTag', 'textarea' => 'SimpleTextAreaTag', 'option' => 'SimpleOptionTag', 'label' => 'SimpleLabelTag', 'form' => 'SimpleFormTag', 'frame' => 'SimpleFrameTag'); $attributes = $this->keysToLowerCase($attributes); if (array_key_exists($name, $map)) { $tag_class = $map[$name]; return new $tag_class($attributes); } elseif ($name == 'select') { return $this->createSelectionTag($attributes); } elseif ($name == 'input') { return $this->createInputTag($attributes); } return new SimpleTag($name, $attributes); } /** * Factory for selection fields. * @param hash $attributes Element attributes. * @return SimpleTag Tag object. * @access protected */ protected function createSelectionTag($attributes) { if (isset($attributes['multiple'])) { return new MultipleSelectionTag($attributes); } return new SimpleSelectionTag($attributes); } /** * Factory for input tags. * @param hash $attributes Element attributes. * @return SimpleTag Tag object. * @access protected */ protected function createInputTag($attributes) { if (! isset($attributes['type'])) { return new SimpleTextTag($attributes); } $type = strtolower(trim($attributes['type'])); $map = array( 'submit' => 'SimpleSubmitTag', 'image' => 'SimpleImageSubmitTag', 'checkbox' => 'SimpleCheckboxTag', 'radio' => 'SimpleRadioButtonTag', 'text' => 'SimpleTextTag', 'hidden' => 'SimpleTextTag', 'password' => 'SimpleTextTag', 'file' => 'SimpleUploadTag'); if (array_key_exists($type, $map)) { $tag_class = $map[$type]; return new $tag_class($attributes); } return false; } /** * Make the keys lower case for case insensitive look-ups. * @param hash $map Hash to convert. * @return hash Unchanged values, but keys lower case. * @access private */ protected function keysToLowerCase($map) { $lower = array(); foreach ($map as $key => $value) { $lower[strtolower($key)] = $value; } return $lower; } } /** * SAX event handler. Maintains a list of * open tags and dispatches them as they close. * @package SimpleTest * @subpackage WebTester */ class SimplePageBuilder extends SimpleSaxListener { private $tags; private $page; private $private_content_tag; /** * Sets the builder up empty. * @access public */ function __construct() { parent::__construct(); } /** * Frees up any references so as to allow the PHP garbage * collection from unset() to work. * @access public */ function free() { unset($this->tags); unset($this->page); unset($this->private_content_tags); } /** * Reads the raw content and send events * into the page to be built. * @param $response SimpleHttpResponse Fetched response. * @return SimplePage Newly parsed page. * @access public */ function parse($response) { $this->tags = array(); $this->page = $this->createPage($response); $parser = $this->createParser($this); $parser->parse($response->getContent()); $this->page->acceptPageEnd(); return $this->page; } /** * Creates an empty page. * @return SimplePage New unparsed page. * @access protected */ protected function createPage($response) { return new SimplePage($response); } /** * Creates the parser used with the builder. * @param $listener SimpleSaxListener Target of parser. * @return SimpleSaxParser Parser to generate * events for the builder. * @access protected */ protected function createParser(&$listener) { return new SimpleHtmlSaxParser($listener); } /** * Start of element event. Opens a new tag. * @param string $name Element name. * @param hash $attributes Attributes without content * are marked as true. * @return boolean False on parse error. * @access public */ function startElement($name, $attributes) { $factory = new SimpleTagBuilder(); $tag = $factory->createTag($name, $attributes); if (! $tag) { return true; } if ($tag->getTagName() == 'label') { $this->page->acceptLabelStart($tag); $this->openTag($tag); return true; } if ($tag->getTagName() == 'form') { $this->page->acceptFormStart($tag); return true; } if ($tag->getTagName() == 'frameset') { $this->page->acceptFramesetStart($tag); return true; } if ($tag->getTagName() == 'frame') { $this->page->acceptFrame($tag); return true; } if ($tag->isPrivateContent() && ! isset($this->private_content_tag)) { $this->private_content_tag = &$tag; } if ($tag->expectEndTag()) { $this->openTag($tag); return true; } $this->page->acceptTag($tag); return true; } /** * End of element event. * @param string $name Element name. * @return boolean False on parse error. * @access public */ function endElement($name) { if ($name == 'label') { $this->page->acceptLabelEnd(); return true; } if ($name == 'form') { $this->page->acceptFormEnd(); return true; } if ($name == 'frameset') { $this->page->acceptFramesetEnd(); return true; } if ($this->hasNamedTagOnOpenTagStack($name)) { $tag = array_pop($this->tags[$name]); if ($tag->isPrivateContent() && $this->private_content_tag->getTagName() == $name) { unset($this->private_content_tag); } $this->addContentTagToOpenTags($tag); $this->page->acceptTag($tag); return true; } return true; } /** * Test to see if there are any open tags awaiting * closure that match the tag name. * @param string $name Element name. * @return boolean True if any are still open. * @access private */ protected function hasNamedTagOnOpenTagStack($name) { return isset($this->tags[$name]) && (count($this->tags[$name]) > 0); } /** * Unparsed, but relevant data. The data is added * to every open tag. * @param string $text May include unparsed tags. * @return boolean False on parse error. * @access public */ function addContent($text) { if (isset($this->private_content_tag)) { $this->private_content_tag->addContent($text); } else { $this->addContentToAllOpenTags($text); } return true; } /** * Any content fills all currently open tags unless it * is part of an option tag. * @param string $text May include unparsed tags. * @access private */ protected function addContentToAllOpenTags($text) { foreach (array_keys($this->tags) as $name) { for ($i = 0, $count = count($this->tags[$name]); $i < $count; $i++) { $this->tags[$name][$i]->addContent($text); } } } /** * Parsed data in tag form. The parsed tag is added * to every open tag. Used for adding options to select * fields only. * @param SimpleTag $tag Option tags only. * @access private */ protected function addContentTagToOpenTags(&$tag) { if ($tag->getTagName() != 'option') { return; } foreach (array_keys($this->tags) as $name) { for ($i = 0, $count = count($this->tags[$name]); $i < $count; $i++) { $this->tags[$name][$i]->addTag($tag); } } } /** * Opens a tag for receiving content. Multiple tags * will be receiving input at the same time. * @param SimpleTag $tag New content tag. * @access private */ protected function openTag($tag) { $name = $tag->getTagName(); if (! in_array($name, array_keys($this->tags))) { $this->tags[$name] = array(); } $this->tags[$name][] = $tag; } } /** * A wrapper for a web page. * @package SimpleTest * @subpackage WebTester */ class SimplePage { private $links; private $title; private $last_widget; private $label; private $left_over_labels; private $open_forms; private $complete_forms; private $frameset; private $frames; private $frameset_nesting_level; private $transport_error; private $raw; private $text; private $sent; private $headers; private $method; private $url; private $base = false; private $request_data; /** * Parses a page ready to access it's contents. * @param SimpleHttpResponse $response Result of HTTP fetch. * @access public */ function __construct($response = false) { $this->links = array(); $this->title = false; $this->left_over_labels = array(); $this->open_forms = array(); $this->complete_forms = array(); $this->frameset = false; $this->frames = array(); $this->frameset_nesting_level = 0; $this->text = false; if ($response) { $this->extractResponse($response); } else { $this->noResponse(); } } /** * Extracts all of the response information. * @param SimpleHttpResponse $response Response being parsed. * @access private */ protected function extractResponse($response) { $this->transport_error = $response->getError(); $this->raw = $response->getContent(); $this->sent = $response->getSent(); $this->headers = $response->getHeaders(); $this->method = $response->getMethod(); $this->url = $response->getUrl(); $this->request_data = $response->getRequestData(); } /** * Sets up a missing response. * @access private */ protected function noResponse() { $this->transport_error = 'No page fetched yet'; $this->raw = false; $this->sent = false; $this->headers = false; $this->method = 'GET'; $this->url = false; $this->request_data = false; } /** * Original request as bytes sent down the wire. * @return mixed Sent content. * @access public */ function getRequest() { return $this->sent; } /** * Accessor for raw text of page. * @return string Raw unparsed content. * @access public */ function getRaw() { return $this->raw; } /** * Accessor for plain text of page as a text browser * would see it. * @return string Plain text of page. * @access public */ function getText() { if (! $this->text) { $this->text = SimpleHtmlSaxParser::normalise($this->raw); } return $this->text; } /** * Accessor for raw headers of page. * @return string Header block as text. * @access public */ function getHeaders() { if ($this->headers) { return $this->headers->getRaw(); } return false; } /** * Original request method. * @return string GET, POST or HEAD. * @access public */ function getMethod() { return $this->method; } /** * Original resource name. * @return SimpleUrl Current url. * @access public */ function getUrl() { return $this->url; } /** * Base URL if set via BASE tag page url otherwise * @return SimpleUrl Base url. * @access public */ function getBaseUrl() { return $this->base; } /** * Original request data. * @return mixed Sent content. * @access public */ function getRequestData() { return $this->request_data; } /** * Accessor for last error. * @return string Error from last response. * @access public */ function getTransportError() { return $this->transport_error; } /** * Accessor for current MIME type. * @return string MIME type as string; e.g. 'text/html' * @access public */ function getMimeType() { if ($this->headers) { return $this->headers->getMimeType(); } return false; } /** * Accessor for HTTP response code. * @return integer HTTP response code received. * @access public */ function getResponseCode() { if ($this->headers) { return $this->headers->getResponseCode(); } return false; } /** * Accessor for last Authentication type. Only valid * straight after a challenge (401). * @return string Description of challenge type. * @access public */ function getAuthentication() { if ($this->headers) { return $this->headers->getAuthentication(); } return false; } /** * Accessor for last Authentication realm. Only valid * straight after a challenge (401). * @return string Name of security realm. * @access public */ function getRealm() { if ($this->headers) { return $this->headers->getRealm(); } return false; } /** * Accessor for current frame focus. Will be * false as no frames. * @return array Always empty. * @access public */ function getFrameFocus() { return array(); } /** * Sets the focus by index. The integer index starts from 1. * @param integer $choice Chosen frame. * @return boolean Always false. * @access public */ function setFrameFocusByIndex($choice) { return false; } /** * Sets the focus by name. Always fails for a leaf page. * @param string $name Chosen frame. * @return boolean False as no frames. * @access public */ function setFrameFocus($name) { return false; } /** * Clears the frame focus. Does nothing for a leaf page. * @access public */ function clearFrameFocus() { } /** * Adds a tag to the page. * @param SimpleTag $tag Tag to accept. * @access public */ function acceptTag($tag) { if ($tag->getTagName() == "a") { $this->addLink($tag); } elseif ($tag->getTagName() == "base") { $this->setBase($tag); } elseif ($tag->getTagName() == "title") { $this->setTitle($tag); } elseif ($this->isFormElement($tag->getTagName())) { for ($i = 0; $i < count($this->open_forms); $i++) { $this->open_forms[$i]->addWidget($tag); } $this->last_widget = &$tag; } } /** * Opens a label for a described widget. * @param SimpleFormTag $tag Tag to accept. * @access public */ function acceptLabelStart($tag) { $this->label = $tag; unset($this->last_widget); } /** * Closes the most recently opened label. * @access public */ function acceptLabelEnd() { if (isset($this->label)) { if (isset($this->last_widget)) { $this->last_widget->setLabel($this->label->getText()); unset($this->last_widget); } else { $this->left_over_labels[] = SimpleTestCompatibility::copy($this->label); } unset($this->label); } } /** * Tests to see if a tag is a possible form * element. * @param string $name HTML element name. * @return boolean True if form element. * @access private */ protected function isFormElement($name) { return in_array($name, array('input', 'button', 'textarea', 'select')); } /** * Opens a form. New widgets go here. * @param SimpleFormTag $tag Tag to accept. * @access public */ function acceptFormStart($tag) { $this->open_forms[] = new SimpleForm($tag, $this); } /** * Closes the most recently opened form. * @access public */ function acceptFormEnd() { if (count($this->open_forms)) { $this->complete_forms[] = array_pop($this->open_forms); } } /** * Opens a frameset. A frameset may contain nested * frameset tags. * @param SimpleFramesetTag $tag Tag to accept. * @access public */ function acceptFramesetStart($tag) { if (! $this->isLoadingFrames()) { $this->frameset = $tag; } $this->frameset_nesting_level++; } /** * Closes the most recently opened frameset. * @access public */ function acceptFramesetEnd() { if ($this->isLoadingFrames()) { $this->frameset_nesting_level--; } } /** * Takes a single frame tag and stashes it in * the current frame set. * @param SimpleFrameTag $tag Tag to accept. * @access public */ function acceptFrame($tag) { if ($this->isLoadingFrames()) { if ($tag->getAttribute('src')) { $this->frames[] = $tag; } } } /** * Test to see if in the middle of reading * a frameset. * @return boolean True if inframeset. * @access private */ protected function isLoadingFrames() { if (! $this->frameset) { return false; } return ($this->frameset_nesting_level > 0); } /** * Test to see if link is an absolute one. * @param string $url Url to test. * @return boolean True if absolute. * @access protected */ protected function linkIsAbsolute($url) { $parsed = new SimpleUrl($url); return (boolean)($parsed->getScheme() && $parsed->getHost()); } /** * Adds a link to the page. * @param SimpleAnchorTag $tag Link to accept. * @access protected */ protected function addLink($tag) { $this->links[] = $tag; } /** * Marker for end of complete page. Any work in * progress can now be closed. * @access public */ function acceptPageEnd() { while (count($this->open_forms)) { $this->complete_forms[] = array_pop($this->open_forms); } foreach ($this->left_over_labels as $label) { for ($i = 0, $count = count($this->complete_forms); $i < $count; $i++) { $this->complete_forms[$i]->attachLabelBySelector( new SimpleById($label->getFor()), $label->getText()); } } } /** * Test for the presence of a frameset. * @return boolean True if frameset. * @access public */ function hasFrames() { return (boolean)$this->frameset; } /** * Accessor for frame name and source URL for every frame that * will need to be loaded. Immediate children only. * @return boolean/array False if no frameset or * otherwise a hash of frame URLs. * The key is either a numerical * base one index or the name attribute. * @access public */ function getFrameset() { if (! $this->frameset) { return false; } $urls = array(); for ($i = 0; $i < count($this->frames); $i++) { $name = $this->frames[$i]->getAttribute('name'); $url = new SimpleUrl($this->frames[$i]->getAttribute('src')); $urls[$name ? $name : $i + 1] = $this->expandUrl($url); } return $urls; } /** * Fetches a list of loaded frames. * @return array/string Just the URL for a single page. * @access public */ function getFrames() { $url = $this->expandUrl($this->getUrl()); return $url->asString(); } /** * Accessor for a list of all links. * @return array List of urls with scheme of * http or https and hostname. * @access public */ function getUrls() { $all = array(); foreach ($this->links as $link) { $url = $this->getUrlFromLink($link); $all[] = $url->asString(); } return $all; } /** * Accessor for URLs by the link label. Label will match * regardess of whitespace issues and case. * @param string $label Text of link. * @return array List of links with that label. * @access public */ function getUrlsByLabel($label) { $matches = array(); foreach ($this->links as $link) { if ($link->getText() == $label) { $matches[] = $this->getUrlFromLink($link); } } return $matches; } /** * Accessor for a URL by the id attribute. * @param string $id Id attribute of link. * @return SimpleUrl URL with that id of false if none. * @access public */ function getUrlById($id) { foreach ($this->links as $link) { if ($link->getAttribute('id') === (string)$id) { return $this->getUrlFromLink($link); } } return false; } /** * Converts a link tag into a target URL. * @param SimpleAnchor $link Parsed link. * @return SimpleUrl URL with frame target if any. * @access private */ protected function getUrlFromLink($link) { $url = $this->expandUrl($link->getHref()); if ($link->getAttribute('target')) { $url->setTarget($link->getAttribute('target')); } return $url; } /** * Expands expandomatic URLs into fully qualified * URLs. * @param SimpleUrl $url Relative URL. * @return SimpleUrl Absolute URL. * @access public */ function expandUrl($url) { if (! is_object($url)) { $url = new SimpleUrl($url); } $location = $this->getBaseUrl() ? $this->getBaseUrl() : new SimpleUrl(); return $url->makeAbsolute($location->makeAbsolute($this->getUrl())); } /** * Sets the base url for the page. * @param SimpleTag $tag Base URL for page. * @access protected */ protected function setBase($tag) { $url = $tag->getAttribute('href'); $this->base = new SimpleUrl($url); } /** * Sets the title tag contents. * @param SimpleTitleTag $tag Title of page. * @access protected */ protected function setTitle($tag) { $this->title = $tag; } /** * Accessor for parsed title. * @return string Title or false if no title is present. * @access public */ function getTitle() { if ($this->title) { return $this->title->getText(); } return false; } /** * Finds a held form by button label. Will only * search correctly built forms. * @param SimpleSelector $selector Button finder. * @return SimpleForm Form object containing * the button. * @access public */ function &getFormBySubmit($selector) { for ($i = 0; $i < count($this->complete_forms); $i++) { if ($this->complete_forms[$i]->hasSubmit($selector)) { return $this->complete_forms[$i]; } } $null = null; return $null; } /** * Finds a held form by image using a selector. * Will only search correctly built forms. * @param SimpleSelector $selector Image finder. * @return SimpleForm Form object containing * the image. * @access public */ function getFormByImage($selector) { for ($i = 0; $i < count($this->complete_forms); $i++) { if ($this->complete_forms[$i]->hasImage($selector)) { return $this->complete_forms[$i]; } } return null; } /** * Finds a held form by the form ID. A way of * identifying a specific form when we have control * of the HTML code. * @param string $id Form label. * @return SimpleForm Form object containing the matching ID. * @access public */ function getFormById($id) { for ($i = 0; $i < count($this->complete_forms); $i++) { if ($this->complete_forms[$i]->getId() == $id) { return $this->complete_forms[$i]; } } return null; } /** * Sets a field on each form in which the field is * available. * @param SimpleSelector $selector Field finder. * @param string $value Value to set field to. * @return boolean True if value is valid. * @access public */ function setField($selector, $value, $position=false) { $is_set = false; for ($i = 0; $i < count($this->complete_forms); $i++) { if ($this->complete_forms[$i]->setField($selector, $value, $position)) { $is_set = true; } } return $is_set; } /** * Accessor for a form element value within a page. * @param SimpleSelector $selector Field finder. * @return string/boolean A string if the field is * present, false if unchecked * and null if missing. * @access public */ function getField($selector) { for ($i = 0; $i < count($this->complete_forms); $i++) { $value = $this->complete_forms[$i]->getValue($selector); if (isset($value)) { return $value; } } return null; } } ?>Swift-4.2.1/test-suite/lib/simpletest/parser.php100644 0 0 62131 12000050366 17026 0ustar 0 0 $constant) { if (! defined($constant)) { define($constant, $i + 1); } } /**#@-*/ /** * Compounded regular expression. Any of * the contained patterns could match and * when one does, it's label is returned. * @package SimpleTest * @subpackage WebTester */ class ParallelRegex { private $patterns; private $labels; private $regex; private $case; /** * Constructor. Starts with no patterns. * @param boolean $case True for case sensitive, false * for insensitive. * @access public */ function __construct($case) { $this->case = $case; $this->patterns = array(); $this->labels = array(); $this->regex = null; } /** * Adds a pattern with an optional label. * @param string $pattern Perl style regex, but ( and ) * lose the usual meaning. * @param string $label Label of regex to be returned * on a match. * @access public */ function addPattern($pattern, $label = true) { $count = count($this->patterns); $this->patterns[$count] = $pattern; $this->labels[$count] = $label; $this->regex = null; } /** * Attempts to match all patterns at once against * a string. * @param string $subject String to match against. * @param string $match First matched portion of * subject. * @return boolean True on success. * @access public */ function match($subject, &$match) { if (count($this->patterns) == 0) { return false; } if (! preg_match($this->getCompoundedRegex(), $subject, $matches)) { $match = ''; return false; } $match = $matches[0]; for ($i = 1; $i < count($matches); $i++) { if ($matches[$i]) { return $this->labels[$i - 1]; } } return true; } /** * Compounds the patterns into a single * regular expression separated with the * "or" operator. Caches the regex. * Will automatically escape (, ) and / tokens. * @param array $patterns List of patterns in order. * @access private */ protected function getCompoundedRegex() { if ($this->regex == null) { for ($i = 0, $count = count($this->patterns); $i < $count; $i++) { $this->patterns[$i] = '(' . str_replace( array('/', '(', ')'), array('\/', '\(', '\)'), $this->patterns[$i]) . ')'; } $this->regex = "/" . implode("|", $this->patterns) . "/" . $this->getPerlMatchingFlags(); } return $this->regex; } /** * Accessor for perl regex mode flags to use. * @return string Perl regex flags. * @access private */ protected function getPerlMatchingFlags() { return ($this->case ? "msS" : "msSi"); } } /** * States for a stack machine. * @package SimpleTest * @subpackage WebTester */ class SimpleStateStack { private $stack; /** * Constructor. Starts in named state. * @param string $start Starting state name. * @access public */ function __construct($start) { $this->stack = array($start); } /** * Accessor for current state. * @return string State. * @access public */ function getCurrent() { return $this->stack[count($this->stack) - 1]; } /** * Adds a state to the stack and sets it * to be the current state. * @param string $state New state. * @access public */ function enter($state) { array_push($this->stack, $state); } /** * Leaves the current state and reverts * to the previous one. * @return boolean False if we drop off * the bottom of the list. * @access public */ function leave() { if (count($this->stack) == 1) { return false; } array_pop($this->stack); return true; } } /** * Accepts text and breaks it into tokens. * Some optimisation to make the sure the * content is only scanned by the PHP regex * parser once. Lexer modes must not start * with leading underscores. * @package SimpleTest * @subpackage WebTester */ class SimpleLexer { private $regexes; private $parser; private $mode; private $mode_handlers; private $case; /** * Sets up the lexer in case insensitive matching * by default. * @param SimpleSaxParser $parser Handling strategy by * reference. * @param string $start Starting handler. * @param boolean $case True for case sensitive. * @access public */ function __construct($parser, $start = "accept", $case = false) { $this->case = $case; $this->regexes = array(); $this->parser = $parser; $this->mode = new SimpleStateStack($start); $this->mode_handlers = array($start => $start); } /** * Adds a token search pattern for a particular * parsing mode. The pattern does not change the * current mode. * @param string $pattern Perl style regex, but ( and ) * lose the usual meaning. * @param string $mode Should only apply this * pattern when dealing with * this type of input. * @access public */ function addPattern($pattern, $mode = "accept") { if (! isset($this->regexes[$mode])) { $this->regexes[$mode] = new ParallelRegex($this->case); } $this->regexes[$mode]->addPattern($pattern); if (! isset($this->mode_handlers[$mode])) { $this->mode_handlers[$mode] = $mode; } } /** * Adds a pattern that will enter a new parsing * mode. Useful for entering parenthesis, strings, * tags, etc. * @param string $pattern Perl style regex, but ( and ) * lose the usual meaning. * @param string $mode Should only apply this * pattern when dealing with * this type of input. * @param string $new_mode Change parsing to this new * nested mode. * @access public */ function addEntryPattern($pattern, $mode, $new_mode) { if (! isset($this->regexes[$mode])) { $this->regexes[$mode] = new ParallelRegex($this->case); } $this->regexes[$mode]->addPattern($pattern, $new_mode); if (! isset($this->mode_handlers[$new_mode])) { $this->mode_handlers[$new_mode] = $new_mode; } } /** * Adds a pattern that will exit the current mode * and re-enter the previous one. * @param string $pattern Perl style regex, but ( and ) * lose the usual meaning. * @param string $mode Mode to leave. * @access public */ function addExitPattern($pattern, $mode) { if (! isset($this->regexes[$mode])) { $this->regexes[$mode] = new ParallelRegex($this->case); } $this->regexes[$mode]->addPattern($pattern, "__exit"); if (! isset($this->mode_handlers[$mode])) { $this->mode_handlers[$mode] = $mode; } } /** * Adds a pattern that has a special mode. Acts as an entry * and exit pattern in one go, effectively calling a special * parser handler for this token only. * @param string $pattern Perl style regex, but ( and ) * lose the usual meaning. * @param string $mode Should only apply this * pattern when dealing with * this type of input. * @param string $special Use this mode for this one token. * @access public */ function addSpecialPattern($pattern, $mode, $special) { if (! isset($this->regexes[$mode])) { $this->regexes[$mode] = new ParallelRegex($this->case); } $this->regexes[$mode]->addPattern($pattern, "_$special"); if (! isset($this->mode_handlers[$special])) { $this->mode_handlers[$special] = $special; } } /** * Adds a mapping from a mode to another handler. * @param string $mode Mode to be remapped. * @param string $handler New target handler. * @access public */ function mapHandler($mode, $handler) { $this->mode_handlers[$mode] = $handler; } /** * Splits the page text into tokens. Will fail * if the handlers report an error or if no * content is consumed. If successful then each * unparsed and parsed token invokes a call to the * held listener. * @param string $raw Raw HTML text. * @return boolean True on success, else false. * @access public */ function parse($raw) { if (! isset($this->parser)) { return false; } $length = strlen($raw); while (is_array($parsed = $this->reduce($raw))) { list($raw, $unmatched, $matched, $mode) = $parsed; if (! $this->dispatchTokens($unmatched, $matched, $mode)) { return false; } if ($raw === '') { return true; } if (strlen($raw) == $length) { return false; } $length = strlen($raw); } if (! $parsed) { return false; } return $this->invokeParser($raw, LEXER_UNMATCHED); } /** * Sends the matched token and any leading unmatched * text to the parser changing the lexer to a new * mode if one is listed. * @param string $unmatched Unmatched leading portion. * @param string $matched Actual token match. * @param string $mode Mode after match. A boolean * false mode causes no change. * @return boolean False if there was any error * from the parser. * @access private */ protected function dispatchTokens($unmatched, $matched, $mode = false) { if (! $this->invokeParser($unmatched, LEXER_UNMATCHED)) { return false; } if (is_bool($mode)) { return $this->invokeParser($matched, LEXER_MATCHED); } if ($this->isModeEnd($mode)) { if (! $this->invokeParser($matched, LEXER_EXIT)) { return false; } return $this->mode->leave(); } if ($this->isSpecialMode($mode)) { $this->mode->enter($this->decodeSpecial($mode)); if (! $this->invokeParser($matched, LEXER_SPECIAL)) { return false; } return $this->mode->leave(); } $this->mode->enter($mode); return $this->invokeParser($matched, LEXER_ENTER); } /** * Tests to see if the new mode is actually to leave * the current mode and pop an item from the matching * mode stack. * @param string $mode Mode to test. * @return boolean True if this is the exit mode. * @access private */ protected function isModeEnd($mode) { return ($mode === "__exit"); } /** * Test to see if the mode is one where this mode * is entered for this token only and automatically * leaves immediately afterwoods. * @param string $mode Mode to test. * @return boolean True if this is the exit mode. * @access private */ protected function isSpecialMode($mode) { return (strncmp($mode, "_", 1) == 0); } /** * Strips the magic underscore marking single token * modes. * @param string $mode Mode to decode. * @return string Underlying mode name. * @access private */ protected function decodeSpecial($mode) { return substr($mode, 1); } /** * Calls the parser method named after the current * mode. Empty content will be ignored. The lexer * has a parser handler for each mode in the lexer. * @param string $content Text parsed. * @param boolean $is_match Token is recognised rather * than unparsed data. * @access private */ protected function invokeParser($content, $is_match) { if (($content === '') || ($content === false)) { return true; } $handler = $this->mode_handlers[$this->mode->getCurrent()]; return $this->parser->$handler($content, $is_match); } /** * Tries to match a chunk of text and if successful * removes the recognised chunk and any leading * unparsed data. Empty strings will not be matched. * @param string $raw The subject to parse. This is the * content that will be eaten. * @return array/boolean Three item list of unparsed * content followed by the * recognised token and finally the * action the parser is to take. * True if no match, false if there * is a parsing error. * @access private */ protected function reduce($raw) { if ($action = $this->regexes[$this->mode->getCurrent()]->match($raw, $match)) { $unparsed_character_count = strpos($raw, $match); $unparsed = substr($raw, 0, $unparsed_character_count); $raw = substr($raw, $unparsed_character_count + strlen($match)); return array($raw, $unparsed, $match, $action); } return true; } } /** * Breaks HTML into SAX events. * @package SimpleTest * @subpackage WebTester */ class SimpleHtmlLexer extends SimpleLexer { /** * Sets up the lexer with case insensitive matching * and adds the HTML handlers. * @param SimpleSaxParser $parser Handling strategy by * reference. * @access public */ function __construct($parser) { parent::__construct($parser, 'text'); $this->mapHandler('text', 'acceptTextToken'); $this->addSkipping(); foreach ($this->getParsedTags() as $tag) { $this->addTag($tag); } $this->addInTagTokens(); } /** * List of parsed tags. Others are ignored. * @return array List of searched for tags. * @access private */ protected function getParsedTags() { return array('a', 'base', 'title', 'form', 'input', 'button', 'textarea', 'select', 'option', 'frameset', 'frame', 'label'); } /** * The lexer has to skip certain sections such * as server code, client code and styles. * @access private */ protected function addSkipping() { $this->mapHandler('css', 'ignore'); $this->addEntryPattern('addExitPattern('', 'css'); $this->mapHandler('js', 'ignore'); $this->addEntryPattern('addExitPattern('', 'js'); $this->mapHandler('comment', 'ignore'); $this->addEntryPattern('', 'comment'); } /** * Pattern matches to start and end a tag. * @param string $tag Name of tag to scan for. * @access private */ protected function addTag($tag) { $this->addSpecialPattern("", 'text', 'acceptEndToken'); $this->addEntryPattern("<$tag", 'text', 'tag'); } /** * Pattern matches to parse the inside of a tag * including the attributes and their quoting. * @access private */ protected function addInTagTokens() { $this->mapHandler('tag', 'acceptStartToken'); $this->addSpecialPattern('\s+', 'tag', 'ignore'); $this->addAttributeTokens(); $this->addExitPattern('/>', 'tag'); $this->addExitPattern('>', 'tag'); } /** * Matches attributes that are either single quoted, * double quoted or unquoted. * @access private */ protected function addAttributeTokens() { $this->mapHandler('dq_attribute', 'acceptAttributeToken'); $this->addEntryPattern('=\s*"', 'tag', 'dq_attribute'); $this->addPattern("\\\\\"", 'dq_attribute'); $this->addExitPattern('"', 'dq_attribute'); $this->mapHandler('sq_attribute', 'acceptAttributeToken'); $this->addEntryPattern("=\s*'", 'tag', 'sq_attribute'); $this->addPattern("\\\\'", 'sq_attribute'); $this->addExitPattern("'", 'sq_attribute'); $this->mapHandler('uq_attribute', 'acceptAttributeToken'); $this->addSpecialPattern('=\s*[^>\s]*', 'tag', 'uq_attribute'); } } /** * Converts HTML tokens into selected SAX events. * @package SimpleTest * @subpackage WebTester */ class SimpleHtmlSaxParser { private $lexer; private $listener; private $tag; private $attributes; private $current_attribute; /** * Sets the listener. * @param SimpleSaxListener $listener SAX event handler. * @access public */ function __construct($listener) { $this->listener = $listener; $this->lexer = $this->createLexer($this); $this->tag = ''; $this->attributes = array(); $this->current_attribute = ''; } /** * Runs the content through the lexer which * should call back to the acceptors. * @param string $raw Page text to parse. * @return boolean False if parse error. * @access public */ function parse($raw) { return $this->lexer->parse($raw); } /** * Sets up the matching lexer. Starts in 'text' mode. * @param SimpleSaxParser $parser Event generator, usually $self. * @return SimpleLexer Lexer suitable for this parser. * @access public */ static function createLexer(&$parser) { return new SimpleHtmlLexer($parser); } /** * Accepts a token from the tag mode. If the * starting element completes then the element * is dispatched and the current attributes * set back to empty. The element or attribute * name is converted to lower case. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function acceptStartToken($token, $event) { if ($event == LEXER_ENTER) { $this->tag = strtolower(substr($token, 1)); return true; } if ($event == LEXER_EXIT) { $success = $this->listener->startElement( $this->tag, $this->attributes); $this->tag = ''; $this->attributes = array(); return $success; } if ($token != '=') { $this->current_attribute = strtolower(SimpleHtmlSaxParser::decodeHtml($token)); $this->attributes[$this->current_attribute] = ''; } return true; } /** * Accepts a token from the end tag mode. * The element name is converted to lower case. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function acceptEndToken($token, $event) { if (! preg_match('/<\/(.*)>/', $token, $matches)) { return false; } return $this->listener->endElement(strtolower($matches[1])); } /** * Part of the tag data. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function acceptAttributeToken($token, $event) { if ($this->current_attribute) { if ($event == LEXER_UNMATCHED) { $this->attributes[$this->current_attribute] .= SimpleHtmlSaxParser::decodeHtml($token); } if ($event == LEXER_SPECIAL) { $this->attributes[$this->current_attribute] .= preg_replace('/^=\s*/' , '', SimpleHtmlSaxParser::decodeHtml($token)); } } return true; } /** * A character entity. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function acceptEntityToken($token, $event) { } /** * Character data between tags regarded as * important. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function acceptTextToken($token, $event) { return $this->listener->addContent($token); } /** * Incoming data to be ignored. * @param string $token Incoming characters. * @param integer $event Lexer event type. * @return boolean False if parse error. * @access public */ function ignore($token, $event) { return true; } /** * Decodes any HTML entities. * @param string $html Incoming HTML. * @return string Outgoing plain text. * @access public */ static function decodeHtml($html) { return html_entity_decode($html, ENT_QUOTES); } /** * Turns HTML into text browser visible text. Images * are converted to their alt text and tags are supressed. * Entities are converted to their visible representation. * @param string $html HTML to convert. * @return string Plain text. * @access public */ static function normalise($html) { $text = preg_replace('||', '', $html); $text = preg_replace('|]*>.*?|', '', $text); $text = preg_replace('|]*alt\s*=\s*"([^"]*)"[^>]*>|', ' \1 ', $text); $text = preg_replace('|]*alt\s*=\s*\'([^\']*)\'[^>]*>|', ' \1 ', $text); $text = preg_replace('|]*alt\s*=\s*([a-zA-Z_]+)[^>]*>|', ' \1 ', $text); $text = preg_replace('|<[^>]*>|', '', $text); $text = SimpleHtmlSaxParser::decodeHtml($text); $text = preg_replace('|\s+|', ' ', $text); return trim(trim($text), "\xA0"); // TODO: The \xAO is a  . Add a test for this. } } /** * SAX event handler. * @package SimpleTest * @subpackage WebTester * @abstract */ class SimpleSaxListener { /** * Sets the document to write to. * @access public */ function __construct() { } /** * Start of element event. * @param string $name Element name. * @param hash $attributes Name value pairs. * Attributes without content * are marked as true. * @return boolean False on parse error. * @access public */ function startElement($name, $attributes) { } /** * End of element event. * @param string $name Element name. * @return boolean False on parse error. * @access public */ function endElement($name) { } /** * Unparsed, but relevant data. * @param string $text May include unparsed tags. * @return boolean False on parse error. * @access public */ function addContent($text) { } } ?>Swift-4.2.1/test-suite/lib/simpletest/reflection_php4.php100644 0 0 6645 12000050366 20607 0ustar 0 0 _interface = $interface; } /** * Checks that a class has been declared. * @return boolean True if defined. * @access public */ function classExists() { return class_exists($this->_interface); } /** * Needed to kill the autoload feature in PHP5 * for classes created dynamically. * @return boolean True if defined. * @access public */ function classExistsSansAutoload() { return class_exists($this->_interface); } /** * Checks that a class or interface has been * declared. * @return boolean True if defined. * @access public */ function classOrInterfaceExists() { return class_exists($this->_interface); } /** * Needed to kill the autoload feature in PHP5 * for classes created dynamically. * @return boolean True if defined. * @access public */ function classOrInterfaceExistsSansAutoload() { return class_exists($this->_interface); } /** * Gets the list of methods on a class or * interface. * @returns array List of method names. * @access public */ function getMethods() { return get_class_methods($this->_interface); } /** * Gets the list of interfaces from a class. If the * class name is actually an interface then just that * interface is returned. * @returns array List of interfaces. * @access public */ function getInterfaces() { return array(); } /** * Finds the parent class name. * @returns string Parent class name. * @access public */ function getParent() { return strtolower(get_parent_class($this->_interface)); } /** * Determines if the class is abstract, which for PHP 4 * will never be the case. * @returns boolean True if abstract. * @access public */ function isAbstract() { return false; } /** * Determines if the the entity is an interface, which for PHP 4 * will never be the case. * @returns boolean True if interface. * @access public */ function isInterface() { return false; } /** * Scans for final methods, but as it's PHP 4 there * aren't any. * @returns boolean True if the class has a final method. * @access public */ function hasFinal() { return false; } /** * Gets the source code matching the declaration * of a method. * @param string $method Method name. * @access public */ function getSignature($method) { return "function &$method()"; } } ?>Swift-4.2.1/test-suite/lib/simpletest/reflection_php5.php100644 0 0 31003 12000050366 20612 0ustar 0 0 interface = $interface; } /** * Checks that a class has been declared. Versions * before PHP5.0.2 need a check that it's not really * an interface. * @return boolean True if defined. * @access public */ function classExists() { if (! class_exists($this->interface)) { return false; } $reflection = new ReflectionClass($this->interface); return ! $reflection->isInterface(); } /** * Needed to kill the autoload feature in PHP5 * for classes created dynamically. * @return boolean True if defined. * @access public */ function classExistsSansAutoload() { return class_exists($this->interface, false); } /** * Checks that a class or interface has been * declared. * @return boolean True if defined. * @access public */ function classOrInterfaceExists() { return $this->classOrInterfaceExistsWithAutoload($this->interface, true); } /** * Needed to kill the autoload feature in PHP5 * for classes created dynamically. * @return boolean True if defined. * @access public */ function classOrInterfaceExistsSansAutoload() { return $this->classOrInterfaceExistsWithAutoload($this->interface, false); } /** * Needed to select the autoload feature in PHP5 * for classes created dynamically. * @param string $interface Class or interface name. * @param boolean $autoload True totriggerautoload. * @return boolean True if interface defined. * @access private */ protected function classOrInterfaceExistsWithAutoload($interface, $autoload) { if (function_exists('interface_exists')) { if (interface_exists($this->interface, $autoload)) { return true; } } return class_exists($this->interface, $autoload); } /** * Gets the list of methods on a class or * interface. * @returns array List of method names. * @access public */ function getMethods() { return array_unique(get_class_methods($this->interface)); } /** * Gets the list of interfaces from a class. If the * class name is actually an interface then just that * interface is returned. * @returns array List of interfaces. * @access public */ function getInterfaces() { $reflection = new ReflectionClass($this->interface); if ($reflection->isInterface()) { return array($this->interface); } return $this->onlyParents($reflection->getInterfaces()); } /** * Gets the list of methods for the implemented * interfaces only. * @returns array List of enforced method signatures. * @access public */ function getInterfaceMethods() { $methods = array(); foreach ($this->getInterfaces() as $interface) { $methods = array_merge($methods, get_class_methods($interface)); } return array_unique($methods); } /** * Checks to see if the method signature has to be tightly * specified. * @param string $method Method name. * @returns boolean True if enforced. * @access private */ protected function isInterfaceMethod($method) { return in_array($method, $this->getInterfaceMethods()); } /** * Finds the parent class name. * @returns string Parent class name. * @access public */ function getParent() { $reflection = new ReflectionClass($this->interface); $parent = $reflection->getParentClass(); if ($parent) { return $parent->getName(); } return false; } /** * Trivially determines if the class is abstract. * @returns boolean True if abstract. * @access public */ function isAbstract() { $reflection = new ReflectionClass($this->interface); return $reflection->isAbstract(); } /** * Trivially determines if the class is an interface. * @returns boolean True if interface. * @access public */ function isInterface() { $reflection = new ReflectionClass($this->interface); return $reflection->isInterface(); } /** * Scans for final methods, as they screw up inherited * mocks by not allowing you to override them. * @returns boolean True if the class has a final method. * @access public */ function hasFinal() { $reflection = new ReflectionClass($this->interface); foreach ($reflection->getMethods() as $method) { if ($method->isFinal()) { return true; } } return false; } /** * Whittles a list of interfaces down to only the * necessary top level parents. * @param array $interfaces Reflection API interfaces * to reduce. * @returns array List of parent interface names. * @access private */ protected function onlyParents($interfaces) { $parents = array(); $blacklist = array(); foreach ($interfaces as $interface) { foreach($interfaces as $possible_parent) { if ($interface->getName() == $possible_parent->getName()) { continue; } if ($interface->isSubClassOf($possible_parent)) { $blacklist[$possible_parent->getName()] = true; } } if (!isset($blacklist[$interface->getName()])) { $parents[] = $interface->getName(); } } return $parents; } /** * Checks whether a method is abstract or not. * @param string $name Method name. * @return bool true if method is abstract, else false * @access private */ protected function isAbstractMethod($name) { $interface = new ReflectionClass($this->interface); if (! $interface->hasMethod($name)) { return false; } return $interface->getMethod($name)->isAbstract(); } /** * Checks whether a method is the constructor. * @param string $name Method name. * @return bool true if method is the constructor * @access private */ protected function isConstructor($name) { return ($name == '__construct') || ($name == $this->interface); } /** * Checks whether a method is abstract in all parents or not. * @param string $name Method name. * @return bool true if method is abstract in parent, else false * @access private */ protected function isAbstractMethodInParents($name) { $interface = new ReflectionClass($this->interface); $parent = $interface->getParentClass(); while($parent) { if (! $parent->hasMethod($name)) { return false; } if ($parent->getMethod($name)->isAbstract()) { return true; } $parent = $parent->getParentClass(); } return false; } /** * Checks whether a method is static or not. * @param string $name Method name * @return bool true if method is static, else false * @access private */ protected function isStaticMethod($name) { $interface = new ReflectionClass($this->interface); if (! $interface->hasMethod($name)) { return false; } return $interface->getMethod($name)->isStatic(); } /** * Writes the source code matching the declaration * of a method. * @param string $name Method name. * @return string Method signature up to last * bracket. * @access public */ function getSignature($name) { if ($name == '__set') { return 'function __set($key, $value)'; } if ($name == '__call') { return 'function __call($method, $arguments)'; } if (version_compare(phpversion(), '5.1.0', '>=')) { if (in_array($name, array('__get', '__isset', $name == '__unset'))) { return "function {$name}(\$key)"; } } if ($name == '__toString') { return "function $name()"; } // This wonky try-catch is a work around for a faulty method_exists() // in early versions of PHP 5 which would return false for static // methods. The Reflection classes work fine, but hasMethod() // doesn't exist prior to PHP 5.1.0, so we need to use a more crude // detection method. try { $interface = new ReflectionClass($this->interface); $interface->getMethod($name); } catch (ReflectionException $e) { return "function $name()"; } return $this->getFullSignature($name); } /** * For a signature specified in an interface, full * details must be replicated to be a valid implementation. * @param string $name Method name. * @return string Method signature up to last * bracket. * @access private */ protected function getFullSignature($name) { $interface = new ReflectionClass($this->interface); $method = $interface->getMethod($name); $reference = $method->returnsReference() ? '&' : ''; $static = $method->isStatic() ? 'static ' : ''; return "{$static}function $reference$name(" . implode(', ', $this->getParameterSignatures($method)) . ")"; } /** * Gets the source code for each parameter. * @param ReflectionMethod $method Method object from * reflection API * @return array List of strings, each * a snippet of code. * @access private */ protected function getParameterSignatures($method) { $signatures = array(); foreach ($method->getParameters() as $parameter) { $signature = ''; $type = $parameter->getClass(); if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray()) { $signature .= 'array '; } elseif (!is_null($type)) { $signature .= $type->getName() . ' '; } if ($parameter->isPassedByReference()) { $signature .= '&'; } $signature .= '$' . $this->suppressSpurious($parameter->getName()); if ($this->isOptional($parameter)) { $signature .= ' = null'; } $signatures[] = $signature; } return $signatures; } /** * The SPL library has problems with the * Reflection library. In particular, you can * get extra characters in parameter names :(. * @param string $name Parameter name. * @return string Cleaner name. * @access private */ protected function suppressSpurious($name) { return str_replace(array('[', ']', ' '), '', $name); } /** * Test of a reflection parameter being optional * that works with early versions of PHP5. * @param reflectionParameter $parameter Is this optional. * @return boolean True if optional. * @access private */ protected function isOptional($parameter) { if (method_exists($parameter, 'isOptional')) { return $parameter->isOptional(); } return false; } } ?>Swift-4.2.1/test-suite/lib/simpletest/remote.php100644 0 0 6536 12000050366 17014 0ustar 0 0 url = $url; $this->dry_url = $dry_url ? $dry_url : $url; $this->size = false; } /** * Accessor for the test name for subclasses. * @return string Name of the test. * @access public */ function getLabel() { return $this->url; } /** * Runs the top level test for this class. Currently * reads the data as a single chunk. I'll fix this * once I have added iteration to the browser. * @param SimpleReporter $reporter Target of test results. * @returns boolean True if no failures. * @access public */ function run($reporter) { $browser = $this->createBrowser(); $xml = $browser->get($this->url); if (! $xml) { trigger_error('Cannot read remote test URL [' . $this->url . ']'); return false; } $parser = $this->createParser($reporter); if (! $parser->parse($xml)) { trigger_error('Cannot parse incoming XML from [' . $this->url . ']'); return false; } return true; } /** * Creates a new web browser object for fetching * the XML report. * @return SimpleBrowser New browser. * @access protected */ protected function createBrowser() { return new SimpleBrowser(); } /** * Creates the XML parser. * @param SimpleReporter $reporter Target of test results. * @return SimpleTestXmlListener XML reader. * @access protected */ protected function createParser($reporter) { return new SimpleTestXmlParser($reporter); } /** * Accessor for the number of subtests. * @return integer Number of test cases. * @access public */ function getSize() { if ($this->size === false) { $browser = $this->createBrowser(); $xml = $browser->get($this->dry_url); if (! $xml) { trigger_error('Cannot read remote test URL [' . $this->dry_url . ']'); return false; } $reporter = new SimpleReporter(); $parser = $this->createParser($reporter); if (! $parser->parse($xml)) { trigger_error('Cannot parse incoming XML from [' . $this->dry_url . ']'); return false; } $this->size = $reporter->getTestCaseCount(); } return $this->size; } } ?>Swift-4.2.1/test-suite/lib/simpletest/reporter.php100644 0 0 34603 12000050366 17377 0ustar 0 0 character_set = $character_set; } /** * Paints the top of the web page setting the * title to the name of the starting test. * @param string $test_name Name class of test. * @access public */ function paintHeader($test_name) { $this->sendNoCacheHeaders(); print ""; print "\n\n$test_name\n"; print "\n"; print "\n"; print "\n\n"; print "

$test_name

\n"; flush(); } /** * Send the headers necessary to ensure the page is * reloaded on every request. Otherwise you could be * scratching your head over out of date test data. * @access public */ static function sendNoCacheHeaders() { if (! headers_sent()) { header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } } /** * Paints the CSS. Add additional styles here. * @return string CSS code as text. * @access protected */ protected function getCss() { return ".fail { background-color: inherit; color: red; }" . ".pass { background-color: inherit; color: green; }" . " pre { background-color: lightgray; color: inherit; }"; } /** * Paints the end of the test with a summary of * the passes and failures. * @param string $test_name Name class of test. * @access public */ function paintFooter($test_name) { $colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green"); print "
"; print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount(); print " test cases complete:\n"; print "" . $this->getPassCount() . " passes, "; print "" . $this->getFailCount() . " fails and "; print "" . $this->getExceptionCount() . " exceptions."; print "
\n"; print "\n\n"; } /** * Paints the test failure with a breadcrumbs * trail of the nesting test suites below the * top level test. * @param string $message Failure message displayed in * the context of the other tests. * @access public */ function paintFail($message) { parent::paintFail($message); print "Fail: "; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print implode(" -> ", $breadcrumb); print " -> " . $this->htmlEntities($message) . "
\n"; } /** * Paints a PHP error. * @param string $message Message is ignored. * @access public */ function paintError($message) { parent::paintError($message); print "Exception: "; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print implode(" -> ", $breadcrumb); print " -> " . $this->htmlEntities($message) . "
\n"; } /** * Paints a PHP exception. * @param Exception $exception Exception to display. * @access public */ function paintException($exception) { parent::paintException($exception); print "Exception: "; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print implode(" -> ", $breadcrumb); $message = 'Unexpected exception of type [' . get_class($exception) . '] with message ['. $exception->getMessage() . '] in ['. $exception->getFile() . ' line ' . $exception->getLine() . ']'; print " -> " . $this->htmlEntities($message) . "
\n"; } /** * Prints the message for skipping tests. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { parent::paintSkip($message); print "Skipped: "; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print implode(" -> ", $breadcrumb); print " -> " . $this->htmlEntities($message) . "
\n"; } /** * Paints formatted text such as dumped privateiables. * @param string $message Text to show. * @access public */ function paintFormattedMessage($message) { print '
' . $this->htmlEntities($message) . '
'; } /** * Character set adjusted entity conversion. * @param string $message Plain text or Unicode message. * @return string Browser readable message. * @access protected */ protected function htmlEntities($message) { return htmlentities($message, ENT_COMPAT, $this->character_set); } } /** * Sample minimal test displayer. Generates only * failure messages and a pass count. For command * line use. I've tried to make it look like JUnit, * but I wanted to output the errors as they arrived * which meant dropping the dots. * @package SimpleTest * @subpackage UnitTester */ class TextReporter extends SimpleReporter { /** * Does nothing yet. The first output will * be sent on the first test start. * @access public */ function __construct() { parent::__construct(); } /** * Paints the title only. * @param string $test_name Name class of test. * @access public */ function paintHeader($test_name) { if (! SimpleReporter::inCli()) { header('Content-type: text/plain'); } print "$test_name\n"; flush(); } /** * Paints the end of the test with a summary of * the passes and failures. * @param string $test_name Name class of test. * @access public */ function paintFooter($test_name) { if ($this->getFailCount() + $this->getExceptionCount() == 0) { print "OK\n"; } else { print "FAILURES!!!\n"; } print "Test cases run: " . $this->getTestCaseProgress() . "/" . $this->getTestCaseCount() . ", Passes: " . $this->getPassCount() . ", Failures: " . $this->getFailCount() . ", Exceptions: " . $this->getExceptionCount() . "\n"; } /** * Paints the test failure as a stack trace. * @param string $message Failure message displayed in * the context of the other tests. * @access public */ function paintFail($message) { parent::paintFail($message); print $this->getFailCount() . ") $message\n"; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); print "\n"; } /** * Paints a PHP error or exception. * @param string $message Message to be shown. * @access public * @abstract */ function paintError($message) { parent::paintError($message); print "Exception " . $this->getExceptionCount() . "!\n$message\n"; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); print "\n"; } /** * Paints a PHP error or exception. * @param Exception $exception Exception to describe. * @access public * @abstract */ function paintException($exception) { parent::paintException($exception); $message = 'Unexpected exception of type [' . get_class($exception) . '] with message ['. $exception->getMessage() . '] in ['. $exception->getFile() . ' line ' . $exception->getLine() . ']'; print "Exception " . $this->getExceptionCount() . "!\n$message\n"; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); print "\n"; } /** * Prints the message for skipping tests. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { parent::paintSkip($message); print "Skip: $message\n"; } /** * Paints formatted text such as dumped privateiables. * @param string $message Text to show. * @access public */ function paintFormattedMessage($message) { print "$message\n"; flush(); } } /** * Runs just a single test group, a single case or * even a single test within that case. * @package SimpleTest * @subpackage UnitTester */ class SelectiveReporter extends SimpleReporterDecorator { private $just_this_case = false; private $just_this_test = false; private $on; /** * Selects the test case or group to be run, * and optionally a specific test. * @param SimpleScorer $reporter Reporter to receive events. * @param string $just_this_case Only this case or group will run. * @param string $just_this_test Only this test method will run. */ function __construct($reporter, $just_this_case = false, $just_this_test = false) { if (isset($just_this_case) && $just_this_case) { $this->just_this_case = strtolower($just_this_case); $this->off(); } else { $this->on(); } if (isset($just_this_test) && $just_this_test) { $this->just_this_test = strtolower($just_this_test); } parent::__construct($reporter); } /** * Compares criteria to actual the case/group name. * @param string $test_case The incoming test. * @return boolean True if matched. * @access protected */ protected function matchesTestCase($test_case) { return $this->just_this_case == strtolower($test_case); } /** * Compares criteria to actual the test name. If no * name was specified at the beginning, then all tests * can run. * @param string $method The incoming test method. * @return boolean True if matched. * @access protected */ protected function shouldRunTest($test_case, $method) { if ($this->isOn() || $this->matchesTestCase($test_case)) { if ($this->just_this_test) { return $this->just_this_test == strtolower($method); } else { return true; } } return false; } /** * Switch on testing for the group or subgroup. * @access private */ protected function on() { $this->on = true; } /** * Switch off testing for the group or subgroup. * @access private */ protected function off() { $this->on = false; } /** * Is this group actually being tested? * @return boolean True if the current test group is active. * @access private */ protected function isOn() { return $this->on; } /** * Veto everything that doesn't match the method wanted. * @param string $test_case Name of test case. * @param string $method Name of test method. * @return boolean True if test should be run. * @access public */ function shouldInvoke($test_case, $method) { if ($this->shouldRunTest($test_case, $method)) { return $this->reporter->shouldInvoke($test_case, $method); } return false; } /** * Paints the start of a group test. * @param string $test_case Name of test or other label. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_case, $size) { if ($this->just_this_case && $this->matchesTestCase($test_case)) { $this->on(); } $this->reporter->paintGroupStart($test_case, $size); } /** * Paints the end of a group test. * @param string $test_case Name of test or other label. * @access public */ function paintGroupEnd($test_case) { $this->reporter->paintGroupEnd($test_case); if ($this->just_this_case && $this->matchesTestCase($test_case)) { $this->off(); } } } /** * Suppresses skip messages. * @package SimpleTest * @subpackage UnitTester */ class NoSkipsReporter extends SimpleReporterDecorator { /** * Does nothing. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { } } ?>Swift-4.2.1/test-suite/lib/simpletest/scorer.php100644 0 0 57712 12000050366 17040 0ustar 0 0 passes = 0; $this->fails = 0; $this->exceptions = 0; $this->is_dry_run = false; } /** * Signals that the next evaluation will be a dry * run. That is, the structure events will be * recorded, but no tests will be run. * @param boolean $is_dry Dry run if true. * @access public */ function makeDry($is_dry = true) { $this->is_dry_run = $is_dry; } /** * The reporter has a veto on what should be run. * @param string $test_case_name name of test case. * @param string $method Name of test method. * @access public */ function shouldInvoke($test_case_name, $method) { return ! $this->is_dry_run; } /** * Can wrap the invoker in preperation for running * a test. * @param SimpleInvoker $invoker Individual test runner. * @return SimpleInvoker Wrapped test runner. * @access public */ function createInvoker($invoker) { return $invoker; } /** * Accessor for current status. Will be false * if there have been any failures or exceptions. * Used for command line tools. * @return boolean True if no failures. * @access public */ function getStatus() { if ($this->exceptions + $this->fails > 0) { return false; } return true; } /** * Paints the start of a group test. * @param string $test_name Name of test or other label. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_name, $size) { } /** * Paints the end of a group test. * @param string $test_name Name of test or other label. * @access public */ function paintGroupEnd($test_name) { } /** * Paints the start of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseStart($test_name) { } /** * Paints the end of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseEnd($test_name) { } /** * Paints the start of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodStart($test_name) { } /** * Paints the end of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodEnd($test_name) { } /** * Increments the pass count. * @param string $message Message is ignored. * @access public */ function paintPass($message) { $this->passes++; } /** * Increments the fail count. * @param string $message Message is ignored. * @access public */ function paintFail($message) { $this->fails++; } /** * Deals with PHP 4 throwing an error. * @param string $message Text of error formatted by * the test case. * @access public */ function paintError($message) { $this->exceptions++; } /** * Deals with PHP 5 throwing an exception. * @param Exception $exception The actual exception thrown. * @access public */ function paintException($exception) { $this->exceptions++; } /** * Prints the message for skipping tests. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { } /** * Accessor for the number of passes so far. * @return integer Number of passes. * @access public */ function getPassCount() { return $this->passes; } /** * Accessor for the number of fails so far. * @return integer Number of fails. * @access public */ function getFailCount() { return $this->fails; } /** * Accessor for the number of untrapped errors * so far. * @return integer Number of exceptions. * @access public */ function getExceptionCount() { return $this->exceptions; } /** * Paints a simple supplementary message. * @param string $message Text to display. * @access public */ function paintMessage($message) { } /** * Paints a formatted ASCII message such as a * privateiable dump. * @param string $message Text to display. * @access public */ function paintFormattedMessage($message) { } /** * By default just ignores user generated events. * @param string $type Event type as text. * @param mixed $payload Message or object. * @access public */ function paintSignal($type, $payload) { } } /** * Recipient of generated test messages that can display * page footers and headers. Also keeps track of the * test nesting. This is the main base class on which * to build the finished test (page based) displays. * @package SimpleTest * @subpackage UnitTester */ class SimpleReporter extends SimpleScorer { private $test_stack; private $size; private $progress; /** * Starts the display with no results in. * @access public */ function __construct() { parent::__construct(); $this->test_stack = array(); $this->size = null; $this->progress = 0; } /** * Gets the formatter for privateiables and other small * generic data items. * @return SimpleDumper Formatter. * @access public */ function getDumper() { return new SimpleDumper(); } /** * Paints the start of a group test. Will also paint * the page header and footer if this is the * first test. Will stash the size if the first * start. * @param string $test_name Name of test that is starting. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_name, $size) { if (! isset($this->size)) { $this->size = $size; } if (count($this->test_stack) == 0) { $this->paintHeader($test_name); } $this->test_stack[] = $test_name; } /** * Paints the end of a group test. Will paint the page * footer if the stack of tests has unwound. * @param string $test_name Name of test that is ending. * @param integer $progress Number of test cases ending. * @access public */ function paintGroupEnd($test_name) { array_pop($this->test_stack); if (count($this->test_stack) == 0) { $this->paintFooter($test_name); } } /** * Paints the start of a test case. Will also paint * the page header and footer if this is the * first test. Will stash the size if the first * start. * @param string $test_name Name of test that is starting. * @access public */ function paintCaseStart($test_name) { if (! isset($this->size)) { $this->size = 1; } if (count($this->test_stack) == 0) { $this->paintHeader($test_name); } $this->test_stack[] = $test_name; } /** * Paints the end of a test case. Will paint the page * footer if the stack of tests has unwound. * @param string $test_name Name of test that is ending. * @access public */ function paintCaseEnd($test_name) { $this->progress++; array_pop($this->test_stack); if (count($this->test_stack) == 0) { $this->paintFooter($test_name); } } /** * Paints the start of a test method. * @param string $test_name Name of test that is starting. * @access public */ function paintMethodStart($test_name) { $this->test_stack[] = $test_name; } /** * Paints the end of a test method. Will paint the page * footer if the stack of tests has unwound. * @param string $test_name Name of test that is ending. * @access public */ function paintMethodEnd($test_name) { array_pop($this->test_stack); } /** * Paints the test document header. * @param string $test_name First test top level * to start. * @access public * @abstract */ function paintHeader($test_name) { } /** * Paints the test document footer. * @param string $test_name The top level test. * @access public * @abstract */ function paintFooter($test_name) { } /** * Accessor for internal test stack. For * subclasses that need to see the whole test * history for display purposes. * @return array List of methods in nesting order. * @access public */ function getTestList() { return $this->test_stack; } /** * Accessor for total test size in number * of test cases. Null until the first * test is started. * @return integer Total number of cases at start. * @access public */ function getTestCaseCount() { return $this->size; } /** * Accessor for the number of test cases * completed so far. * @return integer Number of ended cases. * @access public */ function getTestCaseProgress() { return $this->progress; } /** * Static check for running in the comand line. * @return boolean True if CLI. * @access public */ static function inCli() { return php_sapi_name() == 'cli'; } } /** * For modifying the behaviour of the visual reporters. * @package SimpleTest * @subpackage UnitTester */ class SimpleReporterDecorator { protected $reporter; /** * Mediates between the reporter and the test case. * @param SimpleScorer $reporter Reporter to receive events. */ function __construct($reporter) { $this->reporter = $reporter; } /** * Signals that the next evaluation will be a dry * run. That is, the structure events will be * recorded, but no tests will be run. * @param boolean $is_dry Dry run if true. * @access public */ function makeDry($is_dry = true) { $this->reporter->makeDry($is_dry); } /** * Accessor for current status. Will be false * if there have been any failures or exceptions. * Used for command line tools. * @return boolean True if no failures. * @access public */ function getStatus() { return $this->reporter->getStatus(); } /** * The reporter has a veto on what should be run. * @param string $test_case_name name of test case. * @param string $method Name of test method. * @return boolean True if test should be run. * @access public */ function shouldInvoke($test_case_name, $method) { return $this->reporter->shouldInvoke($test_case_name, $method); } /** * Can wrap the invoker in preperation for running * a test. * @param SimpleInvoker $invoker Individual test runner. * @return SimpleInvoker Wrapped test runner. * @access public */ function createInvoker($invoker) { return $this->reporter->createInvoker($invoker); } /** * Gets the formatter for privateiables and other small * generic data items. * @return SimpleDumper Formatter. * @access public */ function getDumper() { return $this->reporter->getDumper(); } /** * Paints the start of a group test. * @param string $test_name Name of test or other label. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_name, $size) { $this->reporter->paintGroupStart($test_name, $size); } /** * Paints the end of a group test. * @param string $test_name Name of test or other label. * @access public */ function paintGroupEnd($test_name) { $this->reporter->paintGroupEnd($test_name); } /** * Paints the start of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseStart($test_name) { $this->reporter->paintCaseStart($test_name); } /** * Paints the end of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseEnd($test_name) { $this->reporter->paintCaseEnd($test_name); } /** * Paints the start of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodStart($test_name) { $this->reporter->paintMethodStart($test_name); } /** * Paints the end of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodEnd($test_name) { $this->reporter->paintMethodEnd($test_name); } /** * Chains to the wrapped reporter. * @param string $message Message is ignored. * @access public */ function paintPass($message) { $this->reporter->paintPass($message); } /** * Chains to the wrapped reporter. * @param string $message Message is ignored. * @access public */ function paintFail($message) { $this->reporter->paintFail($message); } /** * Chains to the wrapped reporter. * @param string $message Text of error formatted by * the test case. * @access public */ function paintError($message) { $this->reporter->paintError($message); } /** * Chains to the wrapped reporter. * @param Exception $exception Exception to show. * @access public */ function paintException($exception) { $this->reporter->paintException($exception); } /** * Prints the message for skipping tests. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { $this->reporter->paintSkip($message); } /** * Chains to the wrapped reporter. * @param string $message Text to display. * @access public */ function paintMessage($message) { $this->reporter->paintMessage($message); } /** * Chains to the wrapped reporter. * @param string $message Text to display. * @access public */ function paintFormattedMessage($message) { $this->reporter->paintFormattedMessage($message); } /** * Chains to the wrapped reporter. * @param string $type Event type as text. * @param mixed $payload Message or object. * @return boolean Should return false if this * type of signal should fail the * test suite. * @access public */ function paintSignal($type, $payload) { $this->reporter->paintSignal($type, $payload); } } /** * For sending messages to multiple reporters at * the same time. * @package SimpleTest * @subpackage UnitTester */ class MultipleReporter { private $reporters = array(); /** * Adds a reporter to the subscriber list. * @param SimpleScorer $reporter Reporter to receive events. * @access public */ function attachReporter($reporter) { $this->reporters[] = $reporter; } /** * Signals that the next evaluation will be a dry * run. That is, the structure events will be * recorded, but no tests will be run. * @param boolean $is_dry Dry run if true. * @access public */ function makeDry($is_dry = true) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->makeDry($is_dry); } } /** * Accessor for current status. Will be false * if there have been any failures or exceptions. * If any reporter reports a failure, the whole * suite fails. * @return boolean True if no failures. * @access public */ function getStatus() { for ($i = 0; $i < count($this->reporters); $i++) { if (! $this->reporters[$i]->getStatus()) { return false; } } return true; } /** * The reporter has a veto on what should be run. * It requires all reporters to want to run the method. * @param string $test_case_name name of test case. * @param string $method Name of test method. * @access public */ function shouldInvoke($test_case_name, $method) { for ($i = 0; $i < count($this->reporters); $i++) { if (! $this->reporters[$i]->shouldInvoke($test_case_name, $method)) { return false; } } return true; } /** * Every reporter gets a chance to wrap the invoker. * @param SimpleInvoker $invoker Individual test runner. * @return SimpleInvoker Wrapped test runner. * @access public */ function createInvoker($invoker) { for ($i = 0; $i < count($this->reporters); $i++) { $invoker = $this->reporters[$i]->createInvoker($invoker); } return $invoker; } /** * Gets the formatter for privateiables and other small * generic data items. * @return SimpleDumper Formatter. * @access public */ function getDumper() { return new SimpleDumper(); } /** * Paints the start of a group test. * @param string $test_name Name of test or other label. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_name, $size) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintGroupStart($test_name, $size); } } /** * Paints the end of a group test. * @param string $test_name Name of test or other label. * @access public */ function paintGroupEnd($test_name) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintGroupEnd($test_name); } } /** * Paints the start of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseStart($test_name) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintCaseStart($test_name); } } /** * Paints the end of a test case. * @param string $test_name Name of test or other label. * @access public */ function paintCaseEnd($test_name) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintCaseEnd($test_name); } } /** * Paints the start of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodStart($test_name) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintMethodStart($test_name); } } /** * Paints the end of a test method. * @param string $test_name Name of test or other label. * @access public */ function paintMethodEnd($test_name) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintMethodEnd($test_name); } } /** * Chains to the wrapped reporter. * @param string $message Message is ignored. * @access public */ function paintPass($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintPass($message); } } /** * Chains to the wrapped reporter. * @param string $message Message is ignored. * @access public */ function paintFail($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintFail($message); } } /** * Chains to the wrapped reporter. * @param string $message Text of error formatted by * the test case. * @access public */ function paintError($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintError($message); } } /** * Chains to the wrapped reporter. * @param Exception $exception Exception to display. * @access public */ function paintException($exception) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintException($exception); } } /** * Prints the message for skipping tests. * @param string $message Text of skip condition. * @access public */ function paintSkip($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintSkip($message); } } /** * Chains to the wrapped reporter. * @param string $message Text to display. * @access public */ function paintMessage($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintMessage($message); } } /** * Chains to the wrapped reporter. * @param string $message Text to display. * @access public */ function paintFormattedMessage($message) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintFormattedMessage($message); } } /** * Chains to the wrapped reporter. * @param string $type Event type as text. * @param mixed $payload Message or object. * @return boolean Should return false if this * type of signal should fail the * test suite. * @access public */ function paintSignal($type, $payload) { for ($i = 0; $i < count($this->reporters); $i++) { $this->reporters[$i]->paintSignal($type, $payload); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/selector.php100644 0 0 6412 12000050366 17332 0ustar 0 0 name = $name; } /** * Accessor for name. * @returns string $name Name to match. */ function getName() { return $this->name; } /** * Compares with name attribute of widget. * @param SimpleWidget $widget Control to compare. * @access public */ function isMatch($widget) { return ($widget->getName() == $this->name); } } /** * Used to extract form elements for testing against. * Searches by visible label or alt text. * @package SimpleTest * @subpackage WebTester */ class SimpleByLabel { private $label; /** * Stashes the name for later comparison. * @param string $label Visible text to match. */ function __construct($label) { $this->label = $label; } /** * Comparison. Compares visible text of widget or * related label. * @param SimpleWidget $widget Control to compare. * @access public */ function isMatch($widget) { if (! method_exists($widget, 'isLabel')) { return false; } return $widget->isLabel($this->label); } } /** * Used to extract form elements for testing against. * Searches dy id attribute. * @package SimpleTest * @subpackage WebTester */ class SimpleById { private $id; /** * Stashes the name for later comparison. * @param string $id ID atribute to match. */ function __construct($id) { $this->id = $id; } /** * Comparison. Compares id attribute of widget. * @param SimpleWidget $widget Control to compare. * @access public */ function isMatch($widget) { return $widget->isId($this->id); } } /** * Used to extract form elements for testing against. * Searches by visible label, name or alt text. * @package SimpleTest * @subpackage WebTester */ class SimpleByLabelOrName { private $label; /** * Stashes the name/label for later comparison. * @param string $label Visible text to match. */ function __construct($label) { $this->label = $label; } /** * Comparison. Compares visible text of widget or * related label or name. * @param SimpleWidget $widget Control to compare. * @access public */ function isMatch($widget) { if (method_exists($widget, 'isLabel')) { if ($widget->isLabel($this->label)) { return true; } } return ($widget->getName() == $this->label); } } ?>Swift-4.2.1/test-suite/lib/simpletest/shell_tester.php100644 0 0 24343 12000050366 20232 0ustar 0 0 output = false; } /** * Actually runs the command. Does not trap the * error stream output as this need PHP 4.3+. * @param string $command The actual command line * to run. * @return integer Exit code. * @access public */ function execute($command) { $this->output = false; exec($command, $this->output, $ret); return $ret; } /** * Accessor for the last output. * @return string Output as text. * @access public */ function getOutput() { return implode("\n", $this->output); } /** * Accessor for the last output. * @return array Output as array of lines. * @access public */ function getOutputAsList() { return $this->output; } } /** * Test case for testing of command line scripts and * utilities. Usually scripts that are external to the * PHP code, but support it in some way. * @package SimpleTest * @subpackage UnitTester */ class ShellTestCase extends SimpleTestCase { private $current_shell; private $last_status; private $last_command; /** * Creates an empty test case. Should be subclassed * with test methods for a functional test case. * @param string $label Name of test case. Will use * the class name if none specified. * @access public */ function __construct($label = false) { parent::__construct($label); $this->current_shell = $this->createShell(); $this->last_status = false; $this->last_command = ''; } /** * Executes a command and buffers the results. * @param string $command Command to run. * @return boolean True if zero exit code. * @access public */ function execute($command) { $shell = $this->getShell(); $this->last_status = $shell->execute($command); $this->last_command = $command; return ($this->last_status === 0); } /** * Dumps the output of the last command. * @access public */ function dumpOutput() { $this->dump($this->getOutput()); } /** * Accessor for the last output. * @return string Output as text. * @access public */ function getOutput() { $shell = $this->getShell(); return $shell->getOutput(); } /** * Accessor for the last output. * @return array Output as array of lines. * @access public */ function getOutputAsList() { $shell = $this->getShell(); return $shell->getOutputAsList(); } /** * Called from within the test methods to register * passes and failures. * @param boolean $result Pass on true. * @param string $message Message to display describing * the test state. * @return boolean True on pass * @access public */ function assertTrue($result, $message = false) { return $this->assert(new TrueExpectation(), $result, $message); } /** * Will be true on false and vice versa. False * is the PHP definition of false, so that null, * empty strings, zero and an empty array all count * as false. * @param boolean $result Pass on false. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertFalse($result, $message = '%s') { return $this->assert(new FalseExpectation(), $result, $message); } /** * Will trigger a pass if the two parameters have * the same value only. Otherwise a fail. This * is for testing hand extracted text, etc. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertEqual($first, $second, $message = "%s") { return $this->assert( new EqualExpectation($first), $second, $message); } /** * Will trigger a pass if the two parameters have * a different value. Otherwise a fail. This * is for testing hand extracted text, etc. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNotEqual($first, $second, $message = "%s") { return $this->assert( new NotEqualExpectation($first), $second, $message); } /** * Tests the last status code from the shell. * @param integer $status Expected status of last * command. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertExitCode($status, $message = "%s") { $message = sprintf($message, "Expected status code of [$status] from [" . $this->last_command . "], but got [" . $this->last_status . "]"); return $this->assertTrue($status === $this->last_status, $message); } /** * Attempt to exactly match the combined STDERR and * STDOUT output. * @param string $expected Expected output. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertOutput($expected, $message = "%s") { $shell = $this->getShell(); return $this->assert( new EqualExpectation($expected), $shell->getOutput(), $message); } /** * Scans the output for a Perl regex. If found * anywhere it passes, else it fails. * @param string $pattern Regex to search for. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertOutputPattern($pattern, $message = "%s") { $shell = $this->getShell(); return $this->assert( new PatternExpectation($pattern), $shell->getOutput(), $message); } /** * If a Perl regex is found anywhere in the current * output then a failure is generated, else a pass. * @param string $pattern Regex to search for. * @param $message Message to display. * @return boolean True if pass. * @access public */ function assertNoOutputPattern($pattern, $message = "%s") { $shell = $this->getShell(); return $this->assert( new NoPatternExpectation($pattern), $shell->getOutput(), $message); } /** * File existence check. * @param string $path Full filename and path. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertFileExists($path, $message = "%s") { $message = sprintf($message, "File [$path] should exist"); return $this->assertTrue(file_exists($path), $message); } /** * File non-existence check. * @param string $path Full filename and path. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertFileNotExists($path, $message = "%s") { $message = sprintf($message, "File [$path] should not exist"); return $this->assertFalse(file_exists($path), $message); } /** * Scans a file for a Perl regex. If found * anywhere it passes, else it fails. * @param string $pattern Regex to search for. * @param string $path Full filename and path. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertFilePattern($pattern, $path, $message = "%s") { return $this->assert( new PatternExpectation($pattern), implode('', file($path)), $message); } /** * If a Perl regex is found anywhere in the named * file then a failure is generated, else a pass. * @param string $pattern Regex to search for. * @param string $path Full filename and path. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertNoFilePattern($pattern, $path, $message = "%s") { return $this->assert( new NoPatternExpectation($pattern), implode('', file($path)), $message); } /** * Accessor for current shell. Used for testing the * the tester itself. * @return Shell Current shell. * @access protected */ protected function getShell() { return $this->current_shell; } /** * Factory for the shell to run the command on. * @return Shell New shell object. * @access protected */ protected function createShell() { return new SimpleShell(); } } ?>Swift-4.2.1/test-suite/lib/simpletest/simpletest.php100644 0 0 27615 12000050366 17733 0ustar 0 0 = 0) { require_once(dirname(__FILE__) . '/reflection_php5.php'); } else { require_once(dirname(__FILE__) . '/reflection_php4.php'); } require_once(dirname(__FILE__) . '/default_reporter.php'); require_once(dirname(__FILE__) . '/compatibility.php'); /**#@-*/ /** * Registry and test context. Includes a few * global options that I'm slowly getting rid of. * @package SimpleTest * @subpackage UnitTester */ class SimpleTest { /** * Reads the SimpleTest version from the release file. * @return string Version string. * @access public */ static function getVersion() { $content = file(dirname(__FILE__) . '/VERSION'); return trim($content[0]); } /** * Sets the name of a test case to ignore, usually * because the class is an abstract case that should * not be run. Once PHP4 is dropped this will disappear * as a public method and "abstract" will rule. * @param string $class Add a class to ignore. * @access public */ static function ignore($class) { $registry = &SimpleTest::getRegistry(); $registry['IgnoreList'][strtolower($class)] = true; } /** * Scans the now complete ignore list, and adds * all parent classes to the list. If a class * is not a runnable test case, then it's parents * wouldn't be either. This is syntactic sugar * to cut down on ommissions of ignore()'s or * missing abstract declarations. This cannot * be done whilst loading classes wiithout forcing * a particular order on the class declarations and * the ignore() calls. It's just nice to have the ignore() * calls at the top of the file before the actual declarations. * @param array $classes Class names of interest. * @access public */ static function ignoreParentsIfIgnored($classes) { $registry = &SimpleTest::getRegistry(); foreach ($classes as $class) { if (SimpleTest::isIgnored($class)) { $reflection = new SimpleReflection($class); if ($parent = $reflection->getParent()) { SimpleTest::ignore($parent); } } } } /** * Puts the object to the global pool of 'preferred' objects * which can be retrieved with SimpleTest :: preferred() method. * Instances of the same class are overwritten. * @param object $object Preferred object * @access public * @see preferred() */ static function prefer($object) { $registry = &SimpleTest::getRegistry(); $registry['Preferred'][] = $object; } /** * Retrieves 'preferred' objects from global pool. Class filter * can be applied in order to retrieve the object of the specific * class * @param array|string $classes Allowed classes or interfaces. * @access public * @return array|object|null * @see prefer() */ static function preferred($classes) { if (! is_array($classes)) { $classes = array($classes); } $registry = &SimpleTest::getRegistry(); for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) { foreach ($classes as $class) { if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) { return $registry['Preferred'][$i]; } } } return null; } /** * Test to see if a test case is in the ignore * list. Quite obviously the ignore list should * be a separate object and will be one day. * This method is internal to SimpleTest. Don't * use it. * @param string $class Class name to test. * @return boolean True if should not be run. * @access public */ static function isIgnored($class) { $registry = &SimpleTest::getRegistry(); return isset($registry['IgnoreList'][strtolower($class)]); } /** * Sets proxy to use on all requests for when * testing from behind a firewall. Set host * to false to disable. This will take effect * if there are no other proxy settings. * @param string $proxy Proxy host as URL. * @param string $username Proxy username for authentication. * @param string $password Proxy password for authentication. * @access public */ static function useProxy($proxy, $username = false, $password = false) { $registry = &SimpleTest::getRegistry(); $registry['DefaultProxy'] = $proxy; $registry['DefaultProxyUsername'] = $username; $registry['DefaultProxyPassword'] = $password; } /** * Accessor for default proxy host. * @return string Proxy URL. * @access public */ static function getDefaultProxy() { $registry = &SimpleTest::getRegistry(); return $registry['DefaultProxy']; } /** * Accessor for default proxy username. * @return string Proxy username for authentication. * @access public */ static function getDefaultProxyUsername() { $registry = &SimpleTest::getRegistry(); return $registry['DefaultProxyUsername']; } /** * Accessor for default proxy password. * @return string Proxy password for authentication. * @access public */ static function getDefaultProxyPassword() { $registry = &SimpleTest::getRegistry(); return $registry['DefaultProxyPassword']; } /** * Accessor for global registry of options. * @return hash All stored values. * @access private */ protected static function &getRegistry() { static $registry = false; if (! $registry) { $registry = SimpleTest::getDefaults(); } return $registry; } /** * Accessor for the context of the current * test run. * @return SimpleTestContext Current test run. * @access public */ static function getContext() { static $context = false; if (! $context) { $context = new SimpleTestContext(); } return $context; } /** * Constant default values. * @return hash All registry defaults. * @access private */ protected static function getDefaults() { return array( 'MockBaseClass' => 'SimpleMock', 'IgnoreList' => array(), 'DefaultProxy' => false, 'DefaultProxyUsername' => false, 'DefaultProxyPassword' => false, 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter())); } /** * @deprecated */ static function setMockBaseClass($mock_base) { $registry = &SimpleTest::getRegistry(); $registry['MockBaseClass'] = $mock_base; } /** * @deprecated */ static function getMockBaseClass() { $registry = &SimpleTest::getRegistry(); return $registry['MockBaseClass']; } } /** * Container for all components for a specific * test run. Makes things like error queues * available to PHP event handlers, and also * gets around some nasty reference issues in * the mocks. * @package SimpleTest */ class SimpleTestContext { private $test; private $reporter; private $resources; /** * Clears down the current context. * @access public */ function clear() { $this->resources = array(); } /** * Sets the current test case instance. This * global instance can be used by the mock objects * to send message to the test cases. * @param SimpleTestCase $test Test case to register. * @access public */ function setTest($test) { $this->clear(); $this->test = $test; } /** * Accessor for currently running test case. * @return SimpleTestCase Current test. * @access public */ function getTest() { return $this->test; } /** * Sets the current reporter. This * global instance can be used by the mock objects * to send messages. * @param SimpleReporter $reporter Reporter to register. * @access public */ function setReporter($reporter) { $this->clear(); $this->reporter = $reporter; } /** * Accessor for current reporter. * @return SimpleReporter Current reporter. * @access public */ function getReporter() { return $this->reporter; } /** * Accessor for the Singleton resource. * @return object Global resource. * @access public */ function get($resource) { if (! isset($this->resources[$resource])) { $this->resources[$resource] = new $resource(); } return $this->resources[$resource]; } } /** * Interrogates the stack trace to recover the * failure point. * @package SimpleTest * @subpackage UnitTester */ class SimpleStackTrace { private $prefixes; /** * Stashes the list of target prefixes. * @param array $prefixes List of method prefixes * to search for. */ function __construct($prefixes) { $this->prefixes = $prefixes; } /** * Extracts the last method name that was not within * Simpletest itself. Captures a stack trace if none given. * @param array $stack List of stack frames. * @return string Snippet of test report with line * number and file. * @access public */ function traceMethod($stack = false) { $stack = $stack ? $stack : $this->captureTrace(); foreach ($stack as $frame) { if ($this->frameLiesWithinSimpleTestFolder($frame)) { continue; } if ($this->frameMatchesPrefix($frame)) { return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']'; } } return ''; } /** * Test to see if error is generated by SimpleTest itself. * @param array $frame PHP stack frame. * @return boolean True if a SimpleTest file. * @access private */ protected function frameLiesWithinSimpleTestFolder($frame) { if (isset($frame['file'])) { $path = substr(SIMPLE_TEST, 0, -1); if (strpos($frame['file'], $path) === 0) { if (dirname($frame['file']) == $path) { return true; } } } return false; } /** * Tries to determine if the method call is an assert, etc. * @param array $frame PHP stack frame. * @return boolean True if matches a target. * @access private */ protected function frameMatchesPrefix($frame) { foreach ($this->prefixes as $prefix) { if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) { return true; } } return false; } /** * Grabs a current stack trace. * @return array Fulle trace. * @access private */ protected function captureTrace() { if (function_exists('debug_backtrace')) { return array_reverse(debug_backtrace()); } return array(); } } ?>Swift-4.2.1/test-suite/lib/simpletest/socket.php100644 0 0 21425 12000050366 17023 0ustar 0 0 clearError(); } /** * Test for an outstanding error. * @return boolean True if there is an error. * @access public */ function isError() { return ($this->error != ''); } /** * Accessor for an outstanding error. * @return string Empty string if no error otherwise * the error message. * @access public */ function getError() { return $this->error; } /** * Sets the internal error. * @param string Error message to stash. * @access protected */ function setError($error) { $this->error = $error; } /** * Resets the error state to no error. * @access protected */ function clearError() { $this->setError(''); } } class SimpleFileSocket extends SimpleStickyError { private $handle; private $is_open = false; private $sent = ''; private $block_size; /** * Opens a socket for reading and writing. * @param SimpleUrl $file Target URI to fetch. * @param integer $block_size Size of chunk to read. * @access public */ function __construct($file, $block_size = 1024) { parent::__construct(); if (! ($this->handle = $this->openFile($file, $error))) { $file_string = $file->asString(); $this->setError("Cannot open [$file_string] with [$error]"); return; } $this->is_open = true; $this->block_size = $block_size; } /** * Writes some data to the socket and saves alocal copy. * @param string $message String to send to socket. * @return boolean True if successful. * @access public */ function write($message) { return true; } /** * Reads data from the socket. The error suppresion * is a workaround for PHP4 always throwing a warning * with a secure socket. * @return integer/boolean Incoming bytes. False * on error. * @access public */ function read() { $raw = @fread($this->handle, $this->block_size); if ($raw === false) { $this->setError('Cannot read from socket'); $this->close(); } return $raw; } /** * Accessor for socket open state. * @return boolean True if open. * @access public */ function isOpen() { return $this->is_open; } /** * Closes the socket preventing further reads. * Cannot be reopened once closed. * @return boolean True if successful. * @access public */ function close() { if (!$this->is_open) return false; $this->is_open = false; return fclose($this->handle); } /** * Accessor for content so far. * @return string Bytes sent only. * @access public */ function getSent() { return $this->sent; } /** * Actually opens the low level socket. * @param SimpleUrl $file SimpleUrl file target. * @param string $error Recipient of error message. * @param integer $timeout Maximum time to wait for connection. * @access protected */ protected function openFile($file, &$error) { return @fopen($file->asString(), 'r'); } } /** * Wrapper for TCP/IP socket. * @package SimpleTest * @subpackage WebTester */ class SimpleSocket extends SimpleStickyError { private $handle; private $is_open = false; private $sent = ''; private $lock_size; /** * Opens a socket for reading and writing. * @param string $host Hostname to send request to. * @param integer $port Port on remote machine to open. * @param integer $timeout Connection timeout in seconds. * @param integer $block_size Size of chunk to read. * @access public */ function __construct($host, $port, $timeout, $block_size = 255) { parent::__construct(); if (! ($this->handle = $this->openSocket($host, $port, $error_number, $error, $timeout))) { $this->setError("Cannot open [$host:$port] with [$error] within [$timeout] seconds"); return; } $this->is_open = true; $this->block_size = $block_size; SimpleTestCompatibility::setTimeout($this->handle, $timeout); } /** * Writes some data to the socket and saves alocal copy. * @param string $message String to send to socket. * @return boolean True if successful. * @access public */ function write($message) { if ($this->isError() || ! $this->isOpen()) { return false; } $count = fwrite($this->handle, $message); if (! $count) { if ($count === false) { $this->setError('Cannot write to socket'); $this->close(); } return false; } fflush($this->handle); $this->sent .= $message; return true; } /** * Reads data from the socket. The error suppresion * is a workaround for PHP4 always throwing a warning * with a secure socket. * @return integer/boolean Incoming bytes. False * on error. * @access public */ function read() { if ($this->isError() || ! $this->isOpen()) { return false; } $raw = @fread($this->handle, $this->block_size); if ($raw === false) { $this->setError('Cannot read from socket'); $this->close(); } return $raw; } /** * Accessor for socket open state. * @return boolean True if open. * @access public */ function isOpen() { return $this->is_open; } /** * Closes the socket preventing further reads. * Cannot be reopened once closed. * @return boolean True if successful. * @access public */ function close() { $this->is_open = false; return fclose($this->handle); } /** * Accessor for content so far. * @return string Bytes sent only. * @access public */ function getSent() { return $this->sent; } /** * Actually opens the low level socket. * @param string $host Host to connect to. * @param integer $port Port on host. * @param integer $error_number Recipient of error code. * @param string $error Recipoent of error message. * @param integer $timeout Maximum time to wait for connection. * @access protected */ protected function openSocket($host, $port, &$error_number, &$error, $timeout) { return @fsockopen($host, $port, $error_number, $error, $timeout); } } /** * Wrapper for TCP/IP socket over TLS. * @package SimpleTest * @subpackage WebTester */ class SimpleSecureSocket extends SimpleSocket { /** * Opens a secure socket for reading and writing. * @param string $host Hostname to send request to. * @param integer $port Port on remote machine to open. * @param integer $timeout Connection timeout in seconds. * @access public */ function __construct($host, $port, $timeout) { parent::__construct($host, $port, $timeout); } /** * Actually opens the low level socket. * @param string $host Host to connect to. * @param integer $port Port on host. * @param integer $error_number Recipient of error code. * @param string $error Recipient of error message. * @param integer $timeout Maximum time to wait for connection. * @access protected */ function openSocket($host, $port, &$error_number, &$error, $timeout) { return parent::openSocket("tls://$host", $port, $error_number, $error, $timeout); } } ?>Swift-4.2.1/test-suite/lib/simpletest/tag.php100644 0 0 113317 12000050366 16330 0ustar 0 0 name = strtolower(trim($name)); $this->attributes = $attributes; $this->content = ''; } /** * Check to see if the tag can have both start and * end tags with content in between. * @return boolean True if content allowed. * @access public */ function expectEndTag() { return true; } /** * The current tag should not swallow all content for * itself as it's searchable page content. Private * content tags are usually widgets that contain default * values. * @return boolean False as content is available * to other tags by default. * @access public */ function isPrivateContent() { return false; } /** * Appends string content to the current content. * @param string $content Additional text. * @access public */ function addContent($content) { $this->content .= (string)$content; } /** * Adds an enclosed tag to the content. * @param SimpleTag $tag New tag. * @access public */ function addTag($tag) { } /** * Accessor for tag name. * @return string Name of tag. * @access public */ function getTagName() { return $this->name; } /** * List of legal child elements. * @return array List of element names. * @access public */ function getChildElements() { return array(); } /** * Accessor for an attribute. * @param string $label Attribute name. * @return string Attribute value. * @access public */ function getAttribute($label) { $label = strtolower($label); if (! isset($this->attributes[$label])) { return false; } return (string)$this->attributes[$label]; } /** * Sets an attribute. * @param string $label Attribute name. * @return string $value New attribute value. * @access protected */ protected function setAttribute($label, $value) { $this->attributes[strtolower($label)] = $value; } /** * Accessor for the whole content so far. * @return string Content as big raw string. * @access public */ function getContent() { return $this->content; } /** * Accessor for content reduced to visible text. Acts * like a text mode browser, normalising space and * reducing images to their alt text. * @return string Content as plain text. * @access public */ function getText() { return SimpleHtmlSaxParser::normalise($this->content); } /** * Test to see if id attribute matches. * @param string $id ID to test against. * @return boolean True on match. * @access public */ function isId($id) { return ($this->getAttribute('id') == $id); } } /** * Base url. * @package SimpleTest * @subpackage WebTester */ class SimpleBaseTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('base', $attributes); } /** * Base tag is not a block tag. * @return boolean false * @access public */ function expectEndTag() { return false; } } /** * Page title. * @package SimpleTest * @subpackage WebTester */ class SimpleTitleTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('title', $attributes); } } /** * Link. * @package SimpleTest * @subpackage WebTester */ class SimpleAnchorTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('a', $attributes); } /** * Accessor for URL as string. * @return string Coerced as string. * @access public */ function getHref() { $url = $this->getAttribute('href'); if (is_bool($url)) { $url = ''; } return $url; } } /** * Form element. * @package SimpleTest * @subpackage WebTester */ class SimpleWidget extends SimpleTag { private $value; private $label; private $is_set; /** * Starts with a named tag with attributes only. * @param string $name Tag name. * @param hash $attributes Attribute names and * string values. */ function __construct($name, $attributes) { parent::__construct($name, $attributes); $this->value = false; $this->label = false; $this->is_set = false; } /** * Accessor for name submitted as the key in * GET/POST privateiables hash. * @return string Parsed value. * @access public */ function getName() { return $this->getAttribute('name'); } /** * Accessor for default value parsed with the tag. * @return string Parsed value. * @access public */ function getDefault() { return $this->getAttribute('value'); } /** * Accessor for currently set value or default if * none. * @return string Value set by form or default * if none. * @access public */ function getValue() { if (! $this->is_set) { return $this->getDefault(); } return $this->value; } /** * Sets the current form element value. * @param string $value New value. * @return boolean True if allowed. * @access public */ function setValue($value) { $this->value = $value; $this->is_set = true; return true; } /** * Resets the form element value back to the * default. * @access public */ function resetValue() { $this->is_set = false; } /** * Allows setting of a label externally, say by a * label tag. * @param string $label Label to attach. * @access public */ function setLabel($label) { $this->label = trim($label); } /** * Reads external or internal label. * @param string $label Label to test. * @return boolean True is match. * @access public */ function isLabel($label) { return $this->label == trim($label); } /** * Dispatches the value into the form encoded packet. * @param SimpleEncoding $encoding Form packet. * @access public */ function write($encoding) { if ($this->getName()) { $encoding->add($this->getName(), $this->getValue()); } } } /** * Text, password and hidden field. * @package SimpleTest * @subpackage WebTester */ class SimpleTextTag extends SimpleWidget { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('input', $attributes); if ($this->getAttribute('value') === false) { $this->setAttribute('value', ''); } } /** * Tag contains no content. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * Sets the current form element value. Cannot * change the value of a hidden field. * @param string $value New value. * @return boolean True if allowed. * @access public */ function setValue($value) { if ($this->getAttribute('type') == 'hidden') { return false; } return parent::setValue($value); } } /** * Submit button as input tag. * @package SimpleTest * @subpackage WebTester */ class SimpleSubmitTag extends SimpleWidget { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('input', $attributes); if ($this->getAttribute('value') === false) { $this->setAttribute('value', 'Submit'); } } /** * Tag contains no end element. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * Disables the setting of the button value. * @param string $value Ignored. * @return boolean True if allowed. * @access public */ function setValue($value) { return false; } /** * Value of browser visible text. * @return string Visible label. * @access public */ function getLabel() { return $this->getValue(); } /** * Test for a label match when searching. * @param string $label Label to test. * @return boolean True on match. * @access public */ function isLabel($label) { return trim($label) == trim($this->getLabel()); } } /** * Image button as input tag. * @package SimpleTest * @subpackage WebTester */ class SimpleImageSubmitTag extends SimpleWidget { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('input', $attributes); } /** * Tag contains no end element. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * Disables the setting of the button value. * @param string $value Ignored. * @return boolean True if allowed. * @access public */ function setValue($value) { return false; } /** * Value of browser visible text. * @return string Visible label. * @access public */ function getLabel() { if ($this->getAttribute('title')) { return $this->getAttribute('title'); } return $this->getAttribute('alt'); } /** * Test for a label match when searching. * @param string $label Label to test. * @return boolean True on match. * @access public */ function isLabel($label) { return trim($label) == trim($this->getLabel()); } /** * Dispatches the value into the form encoded packet. * @param SimpleEncoding $encoding Form packet. * @param integer $x X coordinate of click. * @param integer $y Y coordinate of click. * @access public */ function write($encoding, $x = 1, $y = 1) { if ($this->getName()) { $encoding->add($this->getName() . '.x', $x); $encoding->add($this->getName() . '.y', $y); } else { $encoding->add('x', $x); $encoding->add('y', $y); } } } /** * Submit button as button tag. * @package SimpleTest * @subpackage WebTester */ class SimpleButtonTag extends SimpleWidget { /** * Starts with a named tag with attributes only. * Defaults are very browser dependent. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('button', $attributes); } /** * Check to see if the tag can have both start and * end tags with content in between. * @return boolean True if content allowed. * @access public */ function expectEndTag() { return true; } /** * Disables the setting of the button value. * @param string $value Ignored. * @return boolean True if allowed. * @access public */ function setValue($value) { return false; } /** * Value of browser visible text. * @return string Visible label. * @access public */ function getLabel() { return $this->getContent(); } /** * Test for a label match when searching. * @param string $label Label to test. * @return boolean True on match. * @access public */ function isLabel($label) { return trim($label) == trim($this->getLabel()); } } /** * Content tag for text area. * @package SimpleTest * @subpackage WebTester */ class SimpleTextAreaTag extends SimpleWidget { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('textarea', $attributes); } /** * Accessor for starting value. * @return string Parsed value. * @access public */ function getDefault() { return $this->wrap(SimpleHtmlSaxParser::decodeHtml($this->getContent())); } /** * Applies word wrapping if needed. * @param string $value New value. * @return boolean True if allowed. * @access public */ function setValue($value) { return parent::setValue($this->wrap($value)); } /** * Test to see if text should be wrapped. * @return boolean True if wrapping on. * @access private */ function wrapIsEnabled() { if ($this->getAttribute('cols')) { $wrap = $this->getAttribute('wrap'); if (($wrap == 'physical') || ($wrap == 'hard')) { return true; } } return false; } /** * Performs the formatting that is peculiar to * this tag. There is strange behaviour in this * one, including stripping a leading new line. * Go figure. I am using Firefox as a guide. * @param string $text Text to wrap. * @return string Text wrapped with carriage * returns and line feeds * @access private */ protected function wrap($text) { $text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text)); $text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text)); if (strncmp($text, "\r\n", strlen("\r\n")) == 0) { $text = substr($text, strlen("\r\n")); } if ($this->wrapIsEnabled()) { return wordwrap( $text, (integer)$this->getAttribute('cols'), "\r\n"); } return $text; } /** * The content of textarea is not part of the page. * @return boolean True. * @access public */ function isPrivateContent() { return true; } } /** * File upload widget. * @package SimpleTest * @subpackage WebTester */ class SimpleUploadTag extends SimpleWidget { /** * Starts with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('input', $attributes); } /** * Tag contains no content. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * Dispatches the value into the form encoded packet. * @param SimpleEncoding $encoding Form packet. * @access public */ function write($encoding) { if (! file_exists($this->getValue())) { return; } $encoding->attach( $this->getName(), implode('', file($this->getValue())), basename($this->getValue())); } } /** * Drop down widget. * @package SimpleTest * @subpackage WebTester */ class SimpleSelectionTag extends SimpleWidget { private $options; private $choice; /** * Starts with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('select', $attributes); $this->options = array(); $this->choice = false; } /** * Adds an option tag to a selection field. * @param SimpleOptionTag $tag New option. * @access public */ function addTag($tag) { if ($tag->getTagName() == 'option') { $this->options[] = $tag; } } /** * Text within the selection element is ignored. * @param string $content Ignored. * @access public */ function addContent($content) { } /** * Scans options for defaults. If none, then * the first option is selected. * @return string Selected field. * @access public */ function getDefault() { for ($i = 0, $count = count($this->options); $i < $count; $i++) { if ($this->options[$i]->getAttribute('selected') !== false) { return $this->options[$i]->getDefault(); } } if ($count > 0) { return $this->options[0]->getDefault(); } return ''; } /** * Can only set allowed values. * @param string $value New choice. * @return boolean True if allowed. * @access public */ function setValue($value) { for ($i = 0, $count = count($this->options); $i < $count; $i++) { if ($this->options[$i]->isValue($value)) { $this->choice = $i; return true; } } return false; } /** * Accessor for current selection value. * @return string Value attribute or * content of opton. * @access public */ function getValue() { if ($this->choice === false) { return $this->getDefault(); } return $this->options[$this->choice]->getValue(); } } /** * Drop down widget. * @package SimpleTest * @subpackage WebTester */ class MultipleSelectionTag extends SimpleWidget { private $options; private $values; /** * Starts with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('select', $attributes); $this->options = array(); $this->values = false; } /** * Adds an option tag to a selection field. * @param SimpleOptionTag $tag New option. * @access public */ function addTag($tag) { if ($tag->getTagName() == 'option') { $this->options[] = &$tag; } } /** * Text within the selection element is ignored. * @param string $content Ignored. * @access public */ function addContent($content) { } /** * Scans options for defaults to populate the * value array(). * @return array Selected fields. * @access public */ function getDefault() { $default = array(); for ($i = 0, $count = count($this->options); $i < $count; $i++) { if ($this->options[$i]->getAttribute('selected') !== false) { $default[] = $this->options[$i]->getDefault(); } } return $default; } /** * Can only set allowed values. Any illegal value * will result in a failure, but all correct values * will be set. * @param array $desired New choices. * @return boolean True if all allowed. * @access public */ function setValue($desired) { $achieved = array(); foreach ($desired as $value) { $success = false; for ($i = 0, $count = count($this->options); $i < $count; $i++) { if ($this->options[$i]->isValue($value)) { $achieved[] = $this->options[$i]->getValue(); $success = true; break; } } if (! $success) { return false; } } $this->values = $achieved; return true; } /** * Accessor for current selection value. * @return array List of currently set options. * @access public */ function getValue() { if ($this->values === false) { return $this->getDefault(); } return $this->values; } } /** * Option for selection field. * @package SimpleTest * @subpackage WebTester */ class SimpleOptionTag extends SimpleWidget { /** * Stashes the attributes. */ function __construct($attributes) { parent::__construct('option', $attributes); } /** * Does nothing. * @param string $value Ignored. * @return boolean Not allowed. * @access public */ function setValue($value) { return false; } /** * Test to see if a value matches the option. * @param string $compare Value to compare with. * @return boolean True if possible match. * @access public */ function isValue($compare) { $compare = trim($compare); if (trim($this->getValue()) == $compare) { return true; } return trim($this->getContent()) == $compare; } /** * Accessor for starting value. Will be set to * the option label if no value exists. * @return string Parsed value. * @access public */ function getDefault() { if ($this->getAttribute('value') === false) { return $this->getContent(); } return $this->getAttribute('value'); } /** * The content of options is not part of the page. * @return boolean True. * @access public */ function isPrivateContent() { return true; } } /** * Radio button. * @package SimpleTest * @subpackage WebTester */ class SimpleRadioButtonTag extends SimpleWidget { /** * Stashes the attributes. * @param array $attributes Hash of attributes. */ function __construct($attributes) { parent::__construct('input', $attributes); if ($this->getAttribute('value') === false) { $this->setAttribute('value', 'on'); } } /** * Tag contains no content. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * The only allowed value sn the one in the * "value" attribute. * @param string $value New value. * @return boolean True if allowed. * @access public */ function setValue($value) { if ($value === false) { return parent::setValue($value); } if ($value != $this->getAttribute('value')) { return false; } return parent::setValue($value); } /** * Accessor for starting value. * @return string Parsed value. * @access public */ function getDefault() { if ($this->getAttribute('checked') !== false) { return $this->getAttribute('value'); } return false; } } /** * Checkbox widget. * @package SimpleTest * @subpackage WebTester */ class SimpleCheckboxTag extends SimpleWidget { /** * Starts with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('input', $attributes); if ($this->getAttribute('value') === false) { $this->setAttribute('value', 'on'); } } /** * Tag contains no content. * @return boolean False. * @access public */ function expectEndTag() { return false; } /** * The only allowed value in the one in the * "value" attribute. The default for this * attribute is "on". If this widget is set to * true, then the usual value will be taken. * @param string $value New value. * @return boolean True if allowed. * @access public */ function setValue($value) { if ($value === false) { return parent::setValue($value); } if ($value === true) { return parent::setValue($this->getAttribute('value')); } if ($value != $this->getAttribute('value')) { return false; } return parent::setValue($value); } /** * Accessor for starting value. The default * value is "on". * @return string Parsed value. * @access public */ function getDefault() { if ($this->getAttribute('checked') !== false) { return $this->getAttribute('value'); } return false; } } /** * A group of multiple widgets with some shared behaviour. * @package SimpleTest * @subpackage WebTester */ class SimpleTagGroup { private $widgets = array(); /** * Adds a tag to the group. * @param SimpleWidget $widget * @access public */ function addWidget($widget) { $this->widgets[] = $widget; } /** * Accessor to widget set. * @return array All widgets. * @access protected */ protected function &getWidgets() { return $this->widgets; } /** * Accessor for an attribute. * @param string $label Attribute name. * @return boolean Always false. * @access public */ function getAttribute($label) { return false; } /** * Fetches the name for the widget from the first * member. * @return string Name of widget. * @access public */ function getName() { if (count($this->widgets) > 0) { return $this->widgets[0]->getName(); } } /** * Scans the widgets for one with the appropriate * ID field. * @param string $id ID value to try. * @return boolean True if matched. * @access public */ function isId($id) { for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { if ($this->widgets[$i]->isId($id)) { return true; } } return false; } /** * Scans the widgets for one with the appropriate * attached label. * @param string $label Attached label to try. * @return boolean True if matched. * @access public */ function isLabel($label) { for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { if ($this->widgets[$i]->isLabel($label)) { return true; } } return false; } /** * Dispatches the value into the form encoded packet. * @param SimpleEncoding $encoding Form packet. * @access public */ function write($encoding) { $encoding->add($this->getName(), $this->getValue()); } } /** * A group of tags with the same name within a form. * @package SimpleTest * @subpackage WebTester */ class SimpleCheckboxGroup extends SimpleTagGroup { /** * Accessor for current selected widget or false * if none. * @return string/array Widget values or false if none. * @access public */ function getValue() { $values = array(); $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if ($widgets[$i]->getValue() !== false) { $values[] = $widgets[$i]->getValue(); } } return $this->coerceValues($values); } /** * Accessor for starting value that is active. * @return string/array Widget values or false if none. * @access public */ function getDefault() { $values = array(); $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if ($widgets[$i]->getDefault() !== false) { $values[] = $widgets[$i]->getDefault(); } } return $this->coerceValues($values); } /** * Accessor for current set values. * @param string/array/boolean $values Either a single string, a * hash or false for nothing set. * @return boolean True if all values can be set. * @access public */ function setValue($values) { $values = $this->makeArray($values); if (! $this->valuesArePossible($values)) { return false; } $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { $possible = $widgets[$i]->getAttribute('value'); if (in_array($widgets[$i]->getAttribute('value'), $values)) { $widgets[$i]->setValue($possible); } else { $widgets[$i]->setValue(false); } } return true; } /** * Tests to see if a possible value set is legal. * @param string/array/boolean $values Either a single string, a * hash or false for nothing set. * @return boolean False if trying to set a * missing value. * @access private */ protected function valuesArePossible($values) { $matches = array(); $widgets = &$this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { $possible = $widgets[$i]->getAttribute('value'); if (in_array($possible, $values)) { $matches[] = $possible; } } return ($values == $matches); } /** * Converts the output to an appropriate format. This means * that no values is false, a single value is just that * value and only two or more are contained in an array. * @param array $values List of values of widgets. * @return string/array/boolean Expected format for a tag. * @access private */ protected function coerceValues($values) { if (count($values) == 0) { return false; } elseif (count($values) == 1) { return $values[0]; } else { return $values; } } /** * Converts false or string into array. The opposite of * the coercian method. * @param string/array/boolean $value A single item is converted * to a one item list. False * gives an empty list. * @return array List of values, possibly empty. * @access private */ protected function makeArray($value) { if ($value === false) { return array(); } if (is_string($value)) { return array($value); } return $value; } } /** * A group of tags with the same name within a form. * Used for radio buttons. * @package SimpleTest * @subpackage WebTester */ class SimpleRadioGroup extends SimpleTagGroup { /** * Each tag is tried in turn until one is * successfully set. The others will be * unchecked if successful. * @param string $value New value. * @return boolean True if any allowed. * @access public */ function setValue($value) { if (! $this->valueIsPossible($value)) { return false; } $index = false; $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if (! $widgets[$i]->setValue($value)) { $widgets[$i]->setValue(false); } } return true; } /** * Tests to see if a value is allowed. * @param string Attempted value. * @return boolean True if a valid value. * @access private */ protected function valueIsPossible($value) { $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if ($widgets[$i]->getAttribute('value') == $value) { return true; } } return false; } /** * Accessor for current selected widget or false * if none. * @return string/boolean Value attribute or * content of opton. * @access public */ function getValue() { $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if ($widgets[$i]->getValue() !== false) { return $widgets[$i]->getValue(); } } return false; } /** * Accessor for starting value that is active. * @return string/boolean Value of first checked * widget or false if none. * @access public */ function getDefault() { $widgets = $this->getWidgets(); for ($i = 0, $count = count($widgets); $i < $count; $i++) { if ($widgets[$i]->getDefault() !== false) { return $widgets[$i]->getDefault(); } } return false; } } /** * Tag to keep track of labels. * @package SimpleTest * @subpackage WebTester */ class SimpleLabelTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('label', $attributes); } /** * Access for the ID to attach the label to. * @return string For attribute. * @access public */ function getFor() { return $this->getAttribute('for'); } } /** * Tag to aid parsing the form. * @package SimpleTest * @subpackage WebTester */ class SimpleFormTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('form', $attributes); } } /** * Tag to aid parsing the frames in a page. * @package SimpleTest * @subpackage WebTester */ class SimpleFrameTag extends SimpleTag { /** * Starts with a named tag with attributes only. * @param hash $attributes Attribute names and * string values. */ function __construct($attributes) { parent::__construct('frame', $attributes); } /** * Tag contains no content. * @return boolean False. * @access public */ function expectEndTag() { return false; } } ?>Swift-4.2.1/test-suite/lib/simpletest/test_case.php100644 0 0 51360 12000050366 17506 0ustar 0 0 label = $label; } } /** * Accessor for the test name for subclasses. * @return string Name of the test. * @access public */ function getLabel() { return $this->label ? $this->label : get_class($this); } /** * This is a placeholder for skipping tests. In this * method you place skipIf() and skipUnless() calls to * set the skipping state. * @access public */ function skip() { } /** * Will issue a message to the reporter and tell the test * case to skip if the incoming flag is true. * @param string $should_skip Condition causing the tests to be skipped. * @param string $message Text of skip condition. * @access public */ function skipIf($should_skip, $message = '%s') { if ($should_skip && ! $this->should_skip) { $this->should_skip = true; $message = sprintf($message, 'Skipping [' . get_class($this) . ']'); $this->reporter->paintSkip($message . $this->getAssertionLine()); } } /** * Accessor for the private variable $_shoud_skip * @access public */ function shouldSkip() { return $this->should_skip; } /** * Will issue a message to the reporter and tell the test * case to skip if the incoming flag is false. * @param string $shouldnt_skip Condition causing the tests to be run. * @param string $message Text of skip condition. * @access public */ function skipUnless($shouldnt_skip, $message = false) { $this->skipIf(! $shouldnt_skip, $message); } /** * Used to invoke the single tests. * @return SimpleInvoker Individual test runner. * @access public */ function createInvoker() { return new SimpleExceptionTrappingInvoker( new SimpleErrorTrappingInvoker(new SimpleInvoker($this))); } /** * Uses reflection to run every method within itself * starting with the string "test" unless a method * is specified. * @param SimpleReporter $reporter Current test reporter. * @return boolean True if all tests passed. * @access public */ function run($reporter) { $context = SimpleTest::getContext(); $context->setTest($this); $context->setReporter($reporter); $this->reporter = $reporter; $started = false; foreach ($this->getTests() as $method) { if ($reporter->shouldInvoke($this->getLabel(), $method)) { $this->skip(); if ($this->should_skip) { break; } if (! $started) { $reporter->paintCaseStart($this->getLabel()); $started = true; } $invoker = $this->reporter->createInvoker($this->createInvoker()); $invoker->before($method); $invoker->invoke($method); $invoker->after($method); } } if ($started) { $reporter->paintCaseEnd($this->getLabel()); } unset($this->reporter); return $reporter->getStatus(); } /** * Gets a list of test names. Normally that will * be all internal methods that start with the * name "test". This method should be overridden * if you want a different rule. * @return array List of test names. * @access public */ function getTests() { $methods = array(); foreach (get_class_methods(get_class($this)) as $method) { if ($this->isTest($method)) { $methods[] = $method; } } return $methods; } /** * Tests to see if the method is a test that should * be run. Currently any method that starts with 'test' * is a candidate unless it is the constructor. * @param string $method Method name to try. * @return boolean True if test method. * @access protected */ protected function isTest($method) { if (strtolower(substr($method, 0, 4)) == 'test') { return ! SimpleTestCompatibility::isA($this, strtolower($method)); } return false; } /** * Announces the start of the test. * @param string $method Test method just started. * @access public */ function before($method) { $this->reporter->paintMethodStart($method); $this->observers = array(); } /** * Sets up unit test wide variables at the start * of each test method. To be overridden in * actual user test cases. * @access public */ function setUp() { } /** * Clears the data set in the setUp() method call. * To be overridden by the user in actual user test cases. * @access public */ function tearDown() { } /** * Announces the end of the test. Includes private clean up. * @param string $method Test method just finished. * @access public */ function after($method) { for ($i = 0; $i < count($this->observers); $i++) { $this->observers[$i]->atTestEnd($method, $this); } $this->reporter->paintMethodEnd($method); } /** * Sets up an observer for the test end. * @param object $observer Must have atTestEnd() * method. * @access public */ function tell($observer) { $this->observers[] = &$observer; } /** * @deprecated */ function pass($message = "Pass") { if (! isset($this->reporter)) { trigger_error('Can only make assertions within test methods'); } $this->reporter->paintPass( $message . $this->getAssertionLine()); return true; } /** * Sends a fail event with a message. * @param string $message Message to send. * @access public */ function fail($message = "Fail") { if (! isset($this->reporter)) { trigger_error('Can only make assertions within test methods'); } $this->reporter->paintFail( $message . $this->getAssertionLine()); return false; } /** * Formats a PHP error and dispatches it to the * reporter. * @param integer $severity PHP error code. * @param string $message Text of error. * @param string $file File error occoured in. * @param integer $line Line number of error. * @access public */ function error($severity, $message, $file, $line) { if (! isset($this->reporter)) { trigger_error('Can only make assertions within test methods'); } $this->reporter->paintError( "Unexpected PHP error [$message] severity [$severity] in [$file line $line]"); } /** * Formats an exception and dispatches it to the * reporter. * @param Exception $exception Object thrown. * @access public */ function exception($exception) { $this->reporter->paintException($exception); } /** * For user defined expansion of the available messages. * @param string $type Tag for sorting the signals. * @param mixed $payload Extra user specific information. */ function signal($type, $payload) { if (! isset($this->reporter)) { trigger_error('Can only make assertions within test methods'); } $this->reporter->paintSignal($type, $payload); } /** * Runs an expectation directly, for extending the * tests with new expectation classes. * @param SimpleExpectation $expectation Expectation subclass. * @param mixed $compare Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assert($expectation, $compare, $message = '%s') { if ($expectation->test($compare)) { return $this->pass(sprintf( $message, $expectation->overlayMessage($compare, $this->reporter->getDumper()))); } else { return $this->fail(sprintf( $message, $expectation->overlayMessage($compare, $this->reporter->getDumper()))); } } /** * Uses a stack trace to find the line of an assertion. * @return string Line number of first assert* * method embedded in format string. * @access public */ function getAssertionLine() { $trace = new SimpleStackTrace(array('assert', 'expect', 'pass', 'fail', 'skip')); return $trace->traceMethod(); } /** * Sends a formatted dump of a variable to the * test suite for those emergency debugging * situations. * @param mixed $variable Variable to display. * @param string $message Message to display. * @return mixed The original variable. * @access public */ function dump($variable, $message = false) { $dumper = $this->reporter->getDumper(); $formatted = $dumper->dump($variable); if ($message) { $formatted = $message . "\n" . $formatted; } $this->reporter->paintFormattedMessage($formatted); return $variable; } /** * Accessor for the number of subtests including myelf. * @return integer Number of test cases. * @access public */ function getSize() { return 1; } } /** * Helps to extract test cases automatically from a file. */ class SimpleFileLoader { /** * Builds a test suite from a library of test cases. * The new suite is composed into this one. * @param string $test_file File name of library with * test case classes. * @return TestSuite The new test suite. * @access public */ function load($test_file) { $existing_classes = get_declared_classes(); $existing_globals = get_defined_vars(); include_once($test_file); $new_globals = get_defined_vars(); $this->makeFileVariablesGlobal($existing_globals, $new_globals); $new_classes = array_diff(get_declared_classes(), $existing_classes); if (empty($new_classes)) { $new_classes = $this->scrapeClassesFromFile($test_file); } $classes = $this->selectRunnableTests($new_classes); return $this->createSuiteFromClasses($test_file, $classes); } /** * Imports new variables into the global namespace. * @param hash $existing Variables before the file was loaded. * @param hash $new Variables after the file was loaded. * @access private */ protected function makeFileVariablesGlobal($existing, $new) { $globals = array_diff(array_keys($new), array_keys($existing)); foreach ($globals as $global) { $_GLOBALS[$global] = $new[$global]; } } /** * Lookup classnames from file contents, in case the * file may have been included before. * Note: This is probably too clever by half. Figuring this * out after a failed test case is going to be tricky for us, * never mind the user. A test case should not be included * twice anyway. * @param string $test_file File name with classes. * @access private */ protected function scrapeClassesFromFile($test_file) { preg_match_all('~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); return $matches[1]; } /** * Calculates the incoming test cases. Skips abstract * and ignored classes. * @param array $candidates Candidate classes. * @return array New classes which are test * cases that shouldn't be ignored. * @access public */ function selectRunnableTests($candidates) { $classes = array(); foreach ($candidates as $class) { if (TestSuite::getBaseTestCase($class)) { $reflection = new SimpleReflection($class); if ($reflection->isAbstract()) { SimpleTest::ignore($class); } else { $classes[] = $class; } } } return $classes; } /** * Builds a test suite from a class list. * @param string $title Title of new group. * @param array $classes Test classes. * @return TestSuite Group loaded with the new * test cases. * @access public */ function createSuiteFromClasses($title, $classes) { if (count($classes) == 0) { $suite = new BadTestSuite($title, "No runnable test cases in [$title]"); return $suite; } SimpleTest::ignoreParentsIfIgnored($classes); $suite = new TestSuite($title); foreach ($classes as $class) { if (! SimpleTest::isIgnored($class)) { $suite->add($class); } } return $suite; } } /** * This is a composite test class for combining * test cases and other RunnableTest classes into * a group test. * @package SimpleTest * @subpackage UnitTester */ class TestSuite { private $label; private $test_cases; /** * Sets the name of the test suite. * @param string $label Name sent at the start and end * of the test. * @access public */ function TestSuite($label = false) { $this->label = $label; $this->test_cases = array(); } /** * Accessor for the test name for subclasses. If the suite * wraps a single test case the label defaults to the name of that test. * @return string Name of the test. * @access public */ function getLabel() { if (! $this->label) { return ($this->getSize() == 1) ? get_class($this->test_cases[0]) : get_class($this); } else { return $this->label; } } /** * Adds a test into the suite by instance or class. The class will * be instantiated if it's a test suite. * @param SimpleTestCase $test_case Suite or individual test * case implementing the * runnable test interface. * @access public */ function add($test_case) { if (! is_string($test_case)) { $this->test_cases[] = $test_case; } elseif (TestSuite::getBaseTestCase($test_case) == 'testsuite') { $this->test_cases[] = new $test_case(); } else { $this->test_cases[] = $test_case; } } /** * Builds a test suite from a library of test cases. * The new suite is composed into this one. * @param string $test_file File name of library with * test case classes. * @access public */ function addFile($test_file) { $extractor = new SimpleFileLoader(); $this->add($extractor->load($test_file)); } /** * Delegates to a visiting collector to add test * files. * @param string $path Path to scan from. * @param SimpleCollector $collector Directory scanner. * @access public */ function collect($path, $collector) { $collector->collect($this, $path); } /** * Invokes run() on all of the held test cases, instantiating * them if necessary. * @param SimpleReporter $reporter Current test reporter. * @access public */ function run($reporter) { $reporter->paintGroupStart($this->getLabel(), $this->getSize()); for ($i = 0, $count = count($this->test_cases); $i < $count; $i++) { if (is_string($this->test_cases[$i])) { $class = $this->test_cases[$i]; $test = new $class(); $test->run($reporter); unset($test); } else { $this->test_cases[$i]->run($reporter); } } $reporter->paintGroupEnd($this->getLabel()); return $reporter->getStatus(); } /** * Number of contained test cases. * @return integer Total count of cases in the group. * @access public */ function getSize() { $count = 0; foreach ($this->test_cases as $case) { if (is_string($case)) { if (! SimpleTest::isIgnored($case)) { $count++; } } else { $count += $case->getSize(); } } return $count; } /** * Test to see if a class is derived from the * SimpleTestCase class. * @param string $class Class name. * @access public */ static function getBaseTestCase($class) { while ($class = get_parent_class($class)) { $class = strtolower($class); if ($class == 'simpletestcase' || $class == 'testsuite') { return $class; } } return false; } } /** * This is a failing group test for when a test suite hasn't * loaded properly. * @package SimpleTest * @subpackage UnitTester */ class BadTestSuite { private $label; private $error; /** * Sets the name of the test suite and error message. * @param string $label Name sent at the start and end * of the test. * @access public */ function BadTestSuite($label, $error) { $this->label = $label; $this->error = $error; } /** * Accessor for the test name for subclasses. * @return string Name of the test. * @access public */ function getLabel() { return $this->label; } /** * Sends a single error to the reporter. * @param SimpleReporter $reporter Current test reporter. * @access public */ function run($reporter) { $reporter->paintGroupStart($this->getLabel(), $this->getSize()); $reporter->paintFail('Bad TestSuite [' . $this->getLabel() . '] with error [' . $this->error . ']'); $reporter->paintGroupEnd($this->getLabel()); return $reporter->getStatus(); } /** * Number of contained test cases. Always zero. * @return integer Total count of cases in the group. * @access public */ function getSize() { return 0; } } ?>Swift-4.2.1/test-suite/lib/simpletest/unit_tester.php100644 0 0 35411 12000050366 20100 0ustar 0 0 assert(new TrueExpectation(), $result, $message); } /** * Will be true on false and vice versa. False * is the PHP definition of false, so that null, * empty strings, zero and an empty array all count * as false. * @param boolean $result Pass on false. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertFalse($result, $message = '%s') { return $this->assert(new FalseExpectation(), $result, $message); } /** * Will be true if the value is null. * @param null $value Supposedly null value. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNull($value, $message = '%s') { $dumper = new SimpleDumper(); $message = sprintf( $message, '[' . $dumper->describeValue($value) . '] should be null'); return $this->assertTrue(! isset($value), $message); } /** * Will be true if the value is set. * @param mixed $value Supposedly set value. * @param string $message Message to display. * @return boolean True on pass. * @access public */ function assertNotNull($value, $message = '%s') { $dumper = new SimpleDumper(); $message = sprintf( $message, '[' . $dumper->describeValue($value) . '] should not be null'); return $this->assertTrue(isset($value), $message); } /** * Type and class test. Will pass if class * matches the type name or is a subclass or * if not an object, but the type is correct. * @param mixed $object Object to test. * @param string $type Type name as string. * @param string $message Message to display. * @return boolean True on pass. * @access public */ function assertIsA($object, $type, $message = '%s') { return $this->assert( new IsAExpectation($type), $object, $message); } /** * Type and class mismatch test. Will pass if class * name or underling type does not match the one * specified. * @param mixed $object Object to test. * @param string $type Type name as string. * @param string $message Message to display. * @return boolean True on pass. * @access public */ function assertNotA($object, $type, $message = '%s') { return $this->assert( new NotAExpectation($type), $object, $message); } /** * Will trigger a pass if the two parameters have * the same value only. Otherwise a fail. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertEqual($first, $second, $message = '%s') { return $this->assert( new EqualExpectation($first), $second, $message); } /** * Will trigger a pass if the two parameters have * a different value. Otherwise a fail. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNotEqual($first, $second, $message = '%s') { return $this->assert( new NotEqualExpectation($first), $second, $message); } /** * Will trigger a pass if the if the first parameter * is near enough to the second by the margin. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param mixed $margin Fuzziness of match. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertWithinMargin($first, $second, $margin, $message = '%s') { return $this->assert( new WithinMarginExpectation($first, $margin), $second, $message); } /** * Will trigger a pass if the two parameters differ * by more than the margin. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param mixed $margin Fuzziness of match. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertOutsideMargin($first, $second, $margin, $message = '%s') { return $this->assert( new OutsideMarginExpectation($first, $margin), $second, $message); } /** * Will trigger a pass if the two parameters have * the same value and same type. Otherwise a fail. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertIdentical($first, $second, $message = '%s') { return $this->assert( new IdenticalExpectation($first), $second, $message); } /** * Will trigger a pass if the two parameters have * the different value or different type. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNotIdentical($first, $second, $message = '%s') { return $this->assert( new NotIdenticalExpectation($first), $second, $message); } /** * Will trigger a pass if both parameters refer * to the same object or value. Fail otherwise. * This will cause problems testing objects under * E_STRICT. * TODO: Replace with expectation. * @param mixed $first Reference to check. * @param mixed $second Hopefully the same variable. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertReference(&$first, &$second, $message = '%s') { $dumper = new SimpleDumper(); $message = sprintf( $message, '[' . $dumper->describeValue($first) . '] and [' . $dumper->describeValue($second) . '] should reference the same object'); return $this->assertTrue( SimpleTestCompatibility::isReference($first, $second), $message); } /** * Will trigger a pass if both parameters refer * to the same object. Fail otherwise. This has * the same semantics at the PHPUnit assertSame. * That is, if values are passed in it has roughly * the same affect as assertIdentical. * TODO: Replace with expectation. * @param mixed $first Object reference to check. * @param mixed $second Hopefully the same object. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertSame($first, $second, $message = '%s') { $dumper = new SimpleDumper(); $message = sprintf( $message, '[' . $dumper->describeValue($first) . '] and [' . $dumper->describeValue($second) . '] should reference the same object'); return $this->assertTrue($first === $second, $message); } /** * Will trigger a pass if both parameters refer * to different objects. Fail otherwise. The objects * have to be identical though. * @param mixed $first Object reference to check. * @param mixed $second Hopefully not the same object. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertClone($first, $second, $message = '%s') { $dumper = new SimpleDumper(); $message = sprintf( $message, '[' . $dumper->describeValue($first) . '] and [' . $dumper->describeValue($second) . '] should not be the same object'); $identical = new IdenticalExpectation($first); return $this->assertTrue( $identical->test($second) && ! ($first === $second), $message); } /** * Will trigger a pass if both parameters refer * to different variables. Fail otherwise. The objects * have to be identical references though. * This will fail under E_STRICT with objects. Use * assertClone() for this. * @param mixed $first Object reference to check. * @param mixed $second Hopefully not the same object. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertCopy(&$first, &$second, $message = "%s") { $dumper = new SimpleDumper(); $message = sprintf( $message, "[" . $dumper->describeValue($first) . "] and [" . $dumper->describeValue($second) . "] should not be the same object"); return $this->assertFalse( SimpleTestCompatibility::isReference($first, $second), $message); } /** * Will trigger a pass if the Perl regex pattern * is found in the subject. Fail otherwise. * @param string $pattern Perl regex to look for including * the regex delimiters. * @param string $subject String to search in. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertPattern($pattern, $subject, $message = '%s') { return $this->assert( new PatternExpectation($pattern), $subject, $message); } /** * Will trigger a pass if the perl regex pattern * is not present in subject. Fail if found. * @param string $pattern Perl regex to look for including * the regex delimiters. * @param string $subject String to search in. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNoPattern($pattern, $subject, $message = '%s') { return $this->assert( new NoPatternExpectation($pattern), $subject, $message); } /** * Prepares for an error. If the error mismatches it * passes through, otherwise it is swallowed. Any * left over errors trigger failures. * @param SimpleExpectation/string $expected The error to match. * @param string $message Message on failure. * @access public */ function expectError($expected = false, $message = '%s') { $queue = SimpleTest::getContext()->get('SimpleErrorQueue'); $queue->expectError($this->coerceExpectation($expected), $message); } /** * Prepares for an exception. If the error mismatches it * passes through, otherwise it is swallowed. Any * left over errors trigger failures. * @param SimpleExpectation/Exception $expected The error to match. * @param string $message Message on failure. * @access public */ function expectException($expected = false, $message = '%s') { $queue = SimpleTest::getContext()->get('SimpleExceptionTrap'); $line = $this->getAssertionLine(); $queue->expectException($expected, $message . $line); } /** * Creates an equality expectation if the * object/value is not already some type * of expectation. * @param mixed $expected Expected value. * @return SimpleExpectation Expectation object. * @access private */ protected function coerceExpectation($expected) { if ($expected == false) { return new TrueExpectation(); } if (SimpleTestCompatibility::isA($expected, 'SimpleExpectation')) { return $expected; } return new EqualExpectation( is_string($expected) ? str_replace('%', '%%', $expected) : $expected); } } ?>Swift-4.2.1/test-suite/lib/simpletest/url.php100644 0 0 42556 12000050366 16345 0ustar 0 0 chompCoordinates($url); $this->setCoordinates($x, $y); $this->scheme = $this->chompScheme($url); if ($this->scheme === 'file') { // Unescaped backslashes not used in directory separator context // will get caught by this, but they should have been urlencoded // anyway so we don't care. If this ends up being a problem, the // host regexp must be modified to match for backslashes when // the scheme is file. $url = str_replace('\\', '/', $url); } list($this->username, $this->password) = $this->chompLogin($url); $this->host = $this->chompHost($url); $this->port = false; if (preg_match('/(.*?):(.*)/', $this->host, $host_parts)) { if ($this->scheme === 'file' && strlen($this->host) === 2) { // DOS drive was placed in authority; promote it to path. $url = '/' . $this->host . $url; $this->host = false; } else { $this->host = $host_parts[1]; $this->port = (integer)$host_parts[2]; } } $this->path = $this->chompPath($url); $this->request = $this->parseRequest($this->chompRequest($url)); $this->fragment = (strncmp($url, "#", 1) == 0 ? substr($url, 1) : false); $this->target = false; } /** * Extracts the X, Y coordinate pair from an image map. * @param string $url URL so far. The coordinates will be * removed. * @return array X, Y as a pair of integers. * @access private */ protected function chompCoordinates(&$url) { if (preg_match('/(.*)\?(\d+),(\d+)$/', $url, $matches)) { $url = $matches[1]; return array((integer)$matches[2], (integer)$matches[3]); } return array(false, false); } /** * Extracts the scheme part of an incoming URL. * @param string $url URL so far. The scheme will be * removed. * @return string Scheme part or false. * @access private */ protected function chompScheme(&$url) { if (preg_match('#^([^/:]*):(//)(.*)#', $url, $matches)) { $url = $matches[2] . $matches[3]; return $matches[1]; } return false; } /** * Extracts the username and password from the * incoming URL. The // prefix will be reattached * to the URL after the doublet is extracted. * @param string $url URL so far. The username and * password are removed. * @return array Two item list of username and * password. Will urldecode() them. * @access private */ protected function chompLogin(&$url) { $prefix = ''; if (preg_match('#^(//)(.*)#', $url, $matches)) { $prefix = $matches[1]; $url = $matches[2]; } if (preg_match('#^([^/]*)@(.*)#', $url, $matches)) { $url = $prefix . $matches[2]; $parts = split(":", $matches[1]); return array( urldecode($parts[0]), isset($parts[1]) ? urldecode($parts[1]) : false); } $url = $prefix . $url; return array(false, false); } /** * Extracts the host part of an incoming URL. * Includes the port number part. Will extract * the host if it starts with // or it has * a top level domain or it has at least two * dots. * @param string $url URL so far. The host will be * removed. * @return string Host part guess or false. * @access private */ protected function chompHost(&$url) { if (preg_match('!^(//)(.*?)(/.*|\?.*|#.*|$)!', $url, $matches)) { $url = $matches[3]; return $matches[2]; } if (preg_match('!(.*?)(\.\./|\./|/|\?|#|$)(.*)!', $url, $matches)) { $tlds = SimpleUrl::getAllTopLevelDomains(); if (preg_match('/[a-z0-9\-]+\.(' . $tlds . ')/i', $matches[1])) { $url = $matches[2] . $matches[3]; return $matches[1]; } elseif (preg_match('/[a-z0-9\-]+\.[a-z0-9\-]+\.[a-z0-9\-]+/i', $matches[1])) { $url = $matches[2] . $matches[3]; return $matches[1]; } } return false; } /** * Extracts the path information from the incoming * URL. Strips this path from the URL. * @param string $url URL so far. The host will be * removed. * @return string Path part or '/'. * @access private */ protected function chompPath(&$url) { if (preg_match('/(.*?)(\?|#|$)(.*)/', $url, $matches)) { $url = $matches[2] . $matches[3]; return ($matches[1] ? $matches[1] : ''); } return ''; } /** * Strips off the request data. * @param string $url URL so far. The request will be * removed. * @return string Raw request part. * @access private */ protected function chompRequest(&$url) { if (preg_match('/\?(.*?)(#|$)(.*)/', $url, $matches)) { $url = $matches[2] . $matches[3]; return $matches[1]; } return ''; } /** * Breaks the request down into an object. * @param string $raw Raw request. * @return SimpleFormEncoding Parsed data. * @access private */ protected function parseRequest($raw) { $this->raw = $raw; $request = new SimpleGetEncoding(); foreach (split("&", $raw) as $pair) { if (preg_match('/(.*?)=(.*)/', $pair, $matches)) { $request->add($matches[1], urldecode($matches[2])); } elseif ($pair) { $request->add($pair, ''); } } return $request; } /** * Accessor for protocol part. * @param string $default Value to use if not present. * @return string Scheme name, e.g "http". * @access public */ function getScheme($default = false) { return $this->scheme ? $this->scheme : $default; } /** * Accessor for user name. * @return string Username preceding host. * @access public */ function getUsername() { return $this->username; } /** * Accessor for password. * @return string Password preceding host. * @access public */ function getPassword() { return $this->password; } /** * Accessor for hostname and port. * @param string $default Value to use if not present. * @return string Hostname only. * @access public */ function getHost($default = false) { return $this->host ? $this->host : $default; } /** * Accessor for top level domain. * @return string Last part of host. * @access public */ function getTld() { $path_parts = pathinfo($this->getHost()); return (isset($path_parts['extension']) ? $path_parts['extension'] : false); } /** * Accessor for port number. * @return integer TCP/IP port number. * @access public */ function getPort() { return $this->port; } /** * Accessor for path. * @return string Full path including leading slash if implied. * @access public */ function getPath() { if (! $this->path && $this->host) { return '/'; } return $this->path; } /** * Accessor for page if any. This may be a * directory name if ambiguious. * @return Page name. * @access public */ function getPage() { if (! preg_match('/([^\/]*?)$/', $this->getPath(), $matches)) { return false; } return $matches[1]; } /** * Gets the path to the page. * @return string Path less the page. * @access public */ function getBasePath() { if (! preg_match('/(.*\/)[^\/]*?$/', $this->getPath(), $matches)) { return false; } return $matches[1]; } /** * Accessor for fragment at end of URL after the "#". * @return string Part after "#". * @access public */ function getFragment() { return $this->fragment; } /** * Sets image coordinates. Set to false to clear * them. * @param integer $x Horizontal position. * @param integer $y Vertical position. * @access public */ function setCoordinates($x = false, $y = false) { if (($x === false) || ($y === false)) { $this->x = $this->y = false; return; } $this->x = (integer)$x; $this->y = (integer)$y; } /** * Accessor for horizontal image coordinate. * @return integer X value. * @access public */ function getX() { return $this->x; } /** * Accessor for vertical image coordinate. * @return integer Y value. * @access public */ function getY() { return $this->y; } /** * Accessor for current request parameters * in URL string form. Will return teh original request * if at all possible even if it doesn't make much * sense. * @return string Form is string "?a=1&b=2", etc. * @access public */ function getEncodedRequest() { if ($this->raw) { $encoded = $this->raw; } else { $encoded = $this->request->asUrlRequest(); } if ($encoded) { return '?' . preg_replace('/^\?/', '', $encoded); } return ''; } /** * Adds an additional parameter to the request. * @param string $key Name of parameter. * @param string $value Value as string. * @access public */ function addRequestParameter($key, $value) { $this->raw = false; $this->request->add($key, $value); } /** * Adds additional parameters to the request. * @param hash/SimpleFormEncoding $parameters Additional * parameters. * @access public */ function addRequestParameters($parameters) { $this->raw = false; $this->request->merge($parameters); } /** * Clears down all parameters. * @access public */ function clearRequest() { $this->raw = false; $this->request = new SimpleGetEncoding(); } /** * Gets the frame target if present. Although * not strictly part of the URL specification it * acts as similarily to the browser. * @return boolean/string Frame name or false if none. * @access public */ function getTarget() { return $this->target; } /** * Attaches a frame target. * @param string $frame Name of frame. * @access public */ function setTarget($frame) { $this->raw = false; $this->target = $frame; } /** * Renders the URL back into a string. * @return string URL in canonical form. * @access public */ function asString() { $path = $this->path; $scheme = $identity = $host = $port = $encoded = $fragment = ''; if ($this->username && $this->password) { $identity = $this->username . ':' . $this->password . '@'; } if ($this->getHost()) { $scheme = $this->getScheme() ? $this->getScheme() : 'http'; $scheme .= '://'; $host = $this->getHost(); } elseif ($this->getScheme() === 'file') { // Safest way; otherwise, file URLs on Windows have an extra // leading slash. It might be possible to convert file:// // URIs to local file paths, but that requires more research. $scheme = 'file://'; } if ($this->getPort() && $this->getPort() != 80 ) { $port = ':'.$this->getPort(); } if (substr($this->path, 0, 1) == '/') { $path = $this->normalisePath($this->path); } $encoded = $this->getEncodedRequest(); $fragment = $this->getFragment() ? '#'. $this->getFragment() : ''; $coords = $this->getX() === false ? '' : '?' . $this->getX() . ',' . $this->getY(); return "$scheme$identity$host$port$path$encoded$fragment$coords"; } /** * Replaces unknown sections to turn a relative * URL into an absolute one. The base URL can * be either a string or a SimpleUrl object. * @param string/SimpleUrl $base Base URL. * @access public */ function makeAbsolute($base) { if (! is_object($base)) { $base = new SimpleUrl($base); } if ($this->getHost()) { $scheme = $this->getScheme(); $host = $this->getHost(); $port = $this->getPort() ? ':' . $this->getPort() : ''; $identity = $this->getIdentity() ? $this->getIdentity() . '@' : ''; if (! $identity) { $identity = $base->getIdentity() ? $base->getIdentity() . '@' : ''; } } else { $scheme = $base->getScheme(); $host = $base->getHost(); $port = $base->getPort() ? ':' . $base->getPort() : ''; $identity = $base->getIdentity() ? $base->getIdentity() . '@' : ''; } $path = $this->normalisePath($this->extractAbsolutePath($base)); $encoded = $this->getEncodedRequest(); $fragment = $this->getFragment() ? '#'. $this->getFragment() : ''; $coords = $this->getX() === false ? '' : '?' . $this->getX() . ',' . $this->getY(); return new SimpleUrl("$scheme://$identity$host$port$path$encoded$fragment$coords"); } /** * Replaces unknown sections of the path with base parts * to return a complete absolute one. * @param string/SimpleUrl $base Base URL. * @param string Absolute path. * @access private */ protected function extractAbsolutePath($base) { if ($this->getHost()) { return $this->path; } if (! $this->isRelativePath($this->path)) { return $this->path; } if ($this->path) { return $base->getBasePath() . $this->path; } return $base->getPath(); } /** * Simple test to see if a path part is relative. * @param string $path Path to test. * @return boolean True if starts with a "/". * @access private */ protected function isRelativePath($path) { return (substr($path, 0, 1) != '/'); } /** * Extracts the username and password for use in rendering * a URL. * @return string/boolean Form of username:password or false. * @access public */ function getIdentity() { if ($this->username && $this->password) { return $this->username . ':' . $this->password; } return false; } /** * Replaces . and .. sections of the path. * @param string $path Unoptimised path. * @return string Path with dots removed if possible. * @access public */ function normalisePath($path) { $path = preg_replace('|/\./|', '/', $path); return preg_replace('|/[^/]+/\.\./|', '/', $path); } /** * A pipe seperated list of all TLDs that result in two part * domain names. * @return string Pipe separated list. * @access public */ static function getAllTopLevelDomains() { return 'com|edu|net|org|gov|mil|int|biz|info|name|pro|aero|coop|museum'; } } ?>Swift-4.2.1/test-suite/lib/simpletest/user_agent.php100644 0 0 26104 12000050366 17666 0ustar 0 0 cookie_jar = new SimpleCookieJar(); $this->authenticator = new SimpleAuthenticator(); } /** * Removes expired and temporary cookies as if * the browser was closed and re-opened. Authorisation * has to be obtained again as well. * @param string/integer $date Time when session restarted. * If omitted then all persistent * cookies are kept. * @access public */ function restart($date = false) { $this->cookie_jar->restartSession($date); $this->authenticator->restartSession(); } /** * Adds a header to every fetch. * @param string $header Header line to add to every * request until cleared. * @access public */ function addHeader($header) { $this->additional_headers[] = $header; } /** * Ages the cookies by the specified time. * @param integer $interval Amount in seconds. * @access public */ function ageCookies($interval) { $this->cookie_jar->agePrematurely($interval); } /** * Sets an additional cookie. If a cookie has * the same name and path it is replaced. * @param string $name Cookie key. * @param string $value Value of cookie. * @param string $host Host upon which the cookie is valid. * @param string $path Cookie path if not host wide. * @param string $expiry Expiry date. * @access public */ function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { $this->cookie_jar->setCookie($name, $value, $host, $path, $expiry); } /** * Reads the most specific cookie value from the * browser cookies. * @param string $host Host to search. * @param string $path Applicable path. * @param string $name Name of cookie to read. * @return string False if not present, else the * value as a string. * @access public */ function getCookieValue($host, $path, $name) { return $this->cookie_jar->getCookieValue($host, $path, $name); } /** * Reads the current cookies within the base URL. * @param string $name Key of cookie to find. * @param SimpleUrl $base Base URL to search from. * @return string/boolean Null if there is no base URL, false * if the cookie is not set. * @access public */ function getBaseCookieValue($name, $base) { if (! $base) { return null; } return $this->getCookieValue($base->getHost(), $base->getPath(), $name); } /** * Switches off cookie sending and recieving. * @access public */ function ignoreCookies() { $this->cookies_enabled = false; } /** * Switches back on the cookie sending and recieving. * @access public */ function useCookies() { $this->cookies_enabled = true; } /** * Sets the socket timeout for opening a connection. * @param integer $timeout Maximum time in seconds. * @access public */ function setConnectionTimeout($timeout) { $this->connection_timeout = $timeout; } /** * Sets the maximum number of redirects before * a page will be loaded anyway. * @param integer $max Most hops allowed. * @access public */ function setMaximumRedirects($max) { $this->max_redirects = $max; } /** * Sets proxy to use on all requests for when * testing from behind a firewall. Set URL * to false to disable. * @param string $proxy Proxy URL. * @param string $username Proxy username for authentication. * @param string $password Proxy password for authentication. * @access public */ function useProxy($proxy, $username, $password) { if (! $proxy) { $this->proxy = false; return; } if ((strncmp($proxy, 'http://', 7) != 0) && (strncmp($proxy, 'https://', 8) != 0)) { $proxy = 'http://'. $proxy; } $this->proxy = new SimpleUrl($proxy); $this->proxy_username = $username; $this->proxy_password = $password; } /** * Test to see if the redirect limit is passed. * @param integer $redirects Count so far. * @return boolean True if over. * @access private */ protected function isTooManyRedirects($redirects) { return ($redirects > $this->max_redirects); } /** * Sets the identity for the current realm. * @param string $host Host to which realm applies. * @param string $realm Full name of realm. * @param string $username Username for realm. * @param string $password Password for realm. * @access public */ function setIdentity($host, $realm, $username, $password) { $this->authenticator->setIdentityForRealm($host, $realm, $username, $password); } /** * Fetches a URL as a response object. Will keep trying if redirected. * It will also collect authentication realm information. * @param string/SimpleUrl $url Target to fetch. * @param SimpleEncoding $encoding Additional parameters for request. * @return SimpleHttpResponse Hopefully the target page. * @access public */ function fetchResponse($url, $encoding) { if ($encoding->getMethod() != 'POST') { $url->addRequestParameters($encoding); $encoding->clear(); } $response = $this->fetchWhileRedirected($url, $encoding); if ($headers = $response->getHeaders()) { if ($headers->isChallenge()) { $this->authenticator->addRealm( $url, $headers->getAuthentication(), $headers->getRealm()); } } return $response; } /** * Fetches the page until no longer redirected or * until the redirect limit runs out. * @param SimpleUrl $url Target to fetch. * @param SimpelFormEncoding $encoding Additional parameters for request. * @return SimpleHttpResponse Hopefully the target page. * @access private */ protected function fetchWhileRedirected($url, $encoding) { $redirects = 0; do { $response = $this->fetch($url, $encoding); if ($response->isError()) { return $response; } $headers = $response->getHeaders(); $location = new SimpleUrl($headers->getLocation()); $url = $location->makeAbsolute($url); if ($this->cookies_enabled) { $headers->writeCookiesToJar($this->cookie_jar, $url); } if (! $headers->isRedirect()) { break; } $encoding = new SimpleGetEncoding(); } while (! $this->isTooManyRedirects(++$redirects)); return $response; } /** * Actually make the web request. * @param SimpleUrl $url Target to fetch. * @param SimpleFormEncoding $encoding Additional parameters for request. * @return SimpleHttpResponse Headers and hopefully content. * @access protected */ protected function fetch($url, $encoding) { $request = $this->createRequest($url, $encoding); return $request->fetch($this->connection_timeout); } /** * Creates a full page request. * @param SimpleUrl $url Target to fetch as url object. * @param SimpleFormEncoding $encoding POST/GET parameters. * @return SimpleHttpRequest New request. * @access private */ protected function createRequest($url, $encoding) { $request = $this->createHttpRequest($url, $encoding); $this->addAdditionalHeaders($request); if ($this->cookies_enabled) { $request->readCookiesFromJar($this->cookie_jar, $url); } $this->authenticator->addHeaders($request, $url); return $request; } /** * Builds the appropriate HTTP request object. * @param SimpleUrl $url Target to fetch as url object. * @param SimpleFormEncoding $parameters POST/GET parameters. * @return SimpleHttpRequest New request object. * @access protected */ protected function createHttpRequest($url, $encoding) { return new SimpleHttpRequest($this->createRoute($url), $encoding); } /** * Sets up either a direct route or via a proxy. * @param SimpleUrl $url Target to fetch as url object. * @return SimpleRoute Route to take to fetch URL. * @access protected */ protected function createRoute($url) { if ($this->proxy) { return new SimpleProxyRoute( $url, $this->proxy, $this->proxy_username, $this->proxy_password); } return new SimpleRoute($url); } /** * Adds additional manual headers. * @param SimpleHttpRequest $request Outgoing request. * @access private */ protected function addAdditionalHeaders(&$request) { foreach ($this->additional_headers as $header) { $request->addHeaderLine($header); } } } ?>Swift-4.2.1/test-suite/lib/simpletest/web_tester.php100644 0 0 150436 12000050366 17723 0ustar 0 0 value = $value; } /** * Tests the expectation. True if it matches * a string value or an array value in any order. * @param mixed $compare Comparison value. False for * an unset field. * @return boolean True if correct. * @access public */ function test($compare) { if ($this->value === false) { return ($compare === false); } if ($this->isSingle($this->value)) { return $this->testSingle($compare); } if (is_array($this->value)) { return $this->testMultiple($compare); } return false; } /** * Tests for valid field comparisons with a single option. * @param mixed $value Value to type check. * @return boolean True if integer, string or float. * @access private */ protected function isSingle($value) { return is_string($value) || is_integer($value) || is_float($value); } /** * String comparison for simple field with a single option. * @param mixed $compare String to test against. * @returns boolean True if matching. * @access private */ protected function testSingle($compare) { if (is_array($compare) && count($compare) == 1) { $compare = $compare[0]; } if (! $this->isSingle($compare)) { return false; } return ($this->value == $compare); } /** * List comparison for multivalue field. * @param mixed $compare List in any order to test against. * @returns boolean True if matching. * @access private */ protected function testMultiple($compare) { if (is_string($compare)) { $compare = array($compare); } if (! is_array($compare)) { return false; } sort($compare); return ($this->value === $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->getDumper(); if (is_array($compare)) { sort($compare); } if ($this->test($compare)) { return "Field expectation [" . $dumper->describeValue($this->value) . "]"; } else { return "Field expectation [" . $dumper->describeValue($this->value) . "] fails with [" . $dumper->describeValue($compare) . "] " . $dumper->describeDifference($this->value, $compare); } } } /** * Test for a specific HTTP header within a header block. * @package SimpleTest * @subpackage WebTester */ class HttpHeaderExpectation extends SimpleExpectation { private $expected_header; private $expected_value; /** * Sets the field and value to compare against. * @param string $header Case insenstive trimmed header name. * @param mixed $value Optional value to compare. If not * given then any value will match. If * an expectation object then that will * be used instead. * @param string $message Optiona message override. Can use %s as * a placeholder for the original message. */ function __construct($header, $value = false, $message = '%s') { parent::__construct($message); $this->expected_header = $this->normaliseHeader($header); $this->expected_value = $value; } /** * Accessor for aggregated object. * @return mixed Expectation set in constructor. * @access protected */ protected function getExpectation() { return $this->expected_value; } /** * Removes whitespace at ends and case variations. * @param string $header Name of header. * @param string Trimmed and lowecased header * name. * @access private */ protected function normaliseHeader($header) { return strtolower(trim($header)); } /** * Tests the expectation. True if it matches * a string value or an array value in any order. * @param mixed $compare Raw header block to search. * @return boolean True if header present. * @access public */ function test($compare) { return is_string($this->findHeader($compare)); } /** * Searches the incoming result. Will extract the matching * line as text. * @param mixed $compare Raw header block to search. * @return string Matching header line. * @access protected */ protected function findHeader($compare) { $lines = split("\r\n", $compare); foreach ($lines as $line) { if ($this->testHeaderLine($line)) { return $line; } } return false; } /** * Compares a single header line against the expectation. * @param string $line A single line to compare. * @return boolean True if matched. * @access private */ protected function testHeaderLine($line) { if (count($parsed = split(':', $line, 2)) < 2) { return false; } list($header, $value) = $parsed; if ($this->normaliseHeader($header) != $this->expected_header) { return false; } return $this->testHeaderValue($value, $this->expected_value); } /** * Tests the value part of the header. * @param string $value Value to test. * @param mixed $expected Value to test against. * @return boolean True if matched. * @access protected */ protected function testHeaderValue($value, $expected) { if ($expected === false) { return true; } if (SimpleExpectation::isExpectation($expected)) { return $expected->test(trim($value)); } return (trim($value) == trim($expected)); } /** * Returns a human readable test message. * @param mixed $compare Raw header block to search. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if (SimpleExpectation::isExpectation($this->expected_value)) { $message = $this->expected_value->overlayMessage($compare, $this->getDumper()); } else { $message = $this->expected_header . ($this->expected_value ? ': ' . $this->expected_value : ''); } if (is_string($line = $this->findHeader($compare))) { return "Searching for header [$message] found [$line]"; } else { return "Failed to find header [$message]"; } } } /** * Test for a specific HTTP header within a header block that * should not be found. * @package SimpleTest * @subpackage WebTester */ class NoHttpHeaderExpectation extends HttpHeaderExpectation { private $expected_header; private $expected_value; /** * Sets the field and value to compare against. * @param string $unwanted Case insenstive trimmed header name. * @param string $message Optiona message override. Can use %s as * a placeholder for the original message. */ function __construct($unwanted, $message = '%s') { parent::__construct($unwanted, false, $message); } /** * Tests that the unwanted header is not found. * @param mixed $compare Raw header block to search. * @return boolean True if header present. * @access public */ function test($compare) { return ($this->findHeader($compare) === false); } /** * Returns a human readable test message. * @param mixed $compare Raw header block to search. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $expectation = $this->getExpectation(); if (is_string($line = $this->findHeader($compare))) { return "Found unwanted header [$expectation] with [$line]"; } else { return "Did not find unwanted header [$expectation]"; } } } /** * Test for a text substring. * @package SimpleTest * @subpackage UnitTester */ class TextExpectation extends SimpleExpectation { private $substring; /** * Sets the value to compare against. * @param string $substring Text to search for. * @param string $message Customised message on failure. * @access public */ function __construct($substring, $message = '%s') { parent::__construct($message); $this->substring = $substring; } /** * Accessor for the substring. * @return string Text to match. * @access protected */ protected function getSubstring() { return $this->substring; } /** * Tests the expectation. True if the text contains the * substring. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (strpos($compare, $this->substring) !== false); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return $this->describeTextMatch($this->getSubstring(), $compare); } else { $dumper = $this->getDumper(); return "Text [" . $this->getSubstring() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } } /** * Describes a pattern match including the string * found and it's position. * @param string $substring Text to search for. * @param string $subject Subject to search. * @access protected */ protected function describeTextMatch($substring, $subject) { $position = strpos($subject, $substring); $dumper = $this->getDumper(); return "Text [$substring] detected at character [$position] in [" . $dumper->describeValue($subject) . "] in region [" . $dumper->clipString($subject, 100, $position) . "]"; } } /** * Fail if a substring is detected within the * comparison text. * @package SimpleTest * @subpackage UnitTester */ class NoTextExpectation extends TextExpectation { /** * Sets the reject pattern * @param string $substring Text to search for. * @param string $message Customised message on failure. * @access public */ function __construct($substring, $message = '%s') { parent::__construct($substring, $message); } /** * Tests the expectation. False if the substring appears * in the text. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param string $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { $dumper = $this->getDumper(); return "Text [" . $this->getSubstring() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } else { return $this->describeTextMatch($this->getSubstring(), $compare); } } } /** * Test case for testing of web pages. Allows * fetching of pages, parsing of HTML and * submitting forms. * @package SimpleTest * @subpackage WebTester */ class WebTestCase extends SimpleTestCase { private $browser; private $ignore_errors = false; /** * Creates an empty test case. Should be subclassed * with test methods for a functional test case. * @param string $label Name of test case. Will use * the class name if none specified. * @access public */ function __construct($label = false) { parent::__construct($label); } /** * Announces the start of the test. * @param string $method Test method just started. * @access public */ function before($method) { parent::before($method); $this->setBrowser($this->createBrowser()); } /** * Announces the end of the test. Includes private clean up. * @param string $method Test method just finished. * @access public */ function after($method) { $this->unsetBrowser(); parent::after($method); } /** * Gets a current browser reference for setting * special expectations or for detailed * examination of page fetches. * @return SimpleBrowser Current test browser object. * @access public */ function getBrowser() { return $this->browser; } /** * Gets a current browser reference for setting * special expectations or for detailed * examination of page fetches. * @param SimpleBrowser $browser New test browser object. * @access public */ function setBrowser($browser) { return $this->browser = $browser; } /** * Clears the current browser reference to help the * PHP garbage collector. * @access public */ function unsetBrowser() { unset($this->browser); } /** * Creates a new default web browser object. * Will be cleared at the end of the test method. * @return TestBrowser New browser. * @access public */ function createBrowser() { return new SimpleBrowser(); } /** * Gets the last response error. * @return string Last low level HTTP error. * @access public */ function getTransportError() { return $this->browser->getTransportError(); } /** * Accessor for the currently selected URL. * @return string Current location or false if * no page yet fetched. * @access public */ function getUrl() { return $this->browser->getUrl(); } /** * Dumps the current request for debugging. * @access public */ function showRequest() { $this->dump($this->browser->getRequest()); } /** * Dumps the current HTTP headers for debugging. * @access public */ function showHeaders() { $this->dump($this->browser->getHeaders()); } /** * Dumps the current HTML source for debugging. * @access public */ function showSource() { $this->dump($this->browser->getContent()); } /** * Dumps the visible text only for debugging. * @access public */ function showText() { $this->dump(wordwrap($this->browser->getContentAsText(), 80)); } /** * Simulates the closing and reopening of the browser. * Temporary cookies will be discarded and timed * cookies will be expired if later than the * specified time. * @param string/integer $date Time when session restarted. * If ommitted then all persistent * cookies are kept. Time is either * Cookie format string or timestamp. * @access public */ function restart($date = false) { if ($date === false) { $date = time(); } $this->browser->restart($date); } /** * Moves cookie expiry times back into the past. * Useful for testing timeouts and expiries. * @param integer $interval Amount to age in seconds. * @access public */ function ageCookies($interval) { $this->browser->ageCookies($interval); } /** * Disables frames support. Frames will not be fetched * and the frameset page will be used instead. * @access public */ function ignoreFrames() { $this->browser->ignoreFrames(); } /** * Switches off cookie sending and recieving. * @access public */ function ignoreCookies() { $this->browser->ignoreCookies(); } /** * Skips errors for the next request only. You might * want to confirm that a page is unreachable for * example. * @access public */ function ignoreErrors() { $this->ignore_errors = true; } /** * Issues a fail if there is a transport error anywhere * in the current frameset. Only one such error is * reported. * @param string/boolean $result HTML or failure. * @return string/boolean $result Passes through result. * @access private */ protected function failOnError($result) { if (! $this->ignore_errors) { if ($error = $this->browser->getTransportError()) { $this->fail($error); } } $this->ignore_errors = false; return $result; } /** * Adds a header to every fetch. * @param string $header Header line to add to every * request until cleared. * @access public */ function addHeader($header) { $this->browser->addHeader($header); } /** * Sets the maximum number of redirects before * the web page is loaded regardless. * @param integer $max Maximum hops. * @access public */ function setMaximumRedirects($max) { if (! $this->browser) { trigger_error( 'Can only set maximum redirects in a test method, setUp() or tearDown()'); } $this->browser->setMaximumRedirects($max); } /** * Sets the socket timeout for opening a connection and * receiving at least one byte of information. * @param integer $timeout Maximum time in seconds. * @access public */ function setConnectionTimeout($timeout) { $this->browser->setConnectionTimeout($timeout); } /** * Sets proxy to use on all requests for when * testing from behind a firewall. Set URL * to false to disable. * @param string $proxy Proxy URL. * @param string $username Proxy username for authentication. * @param string $password Proxy password for authentication. * @access public */ function useProxy($proxy, $username = false, $password = false) { $this->browser->useProxy($proxy, $username, $password); } /** * Fetches a page into the page buffer. If * there is no base for the URL then the * current base URL is used. After the fetch * the base URL reflects the new location. * @param string $url URL to fetch. * @param hash $parameters Optional additional GET data. * @return boolean/string Raw page on success. * @access public */ function get($url, $parameters = false) { return $this->failOnError($this->browser->get($url, $parameters)); } /** * Fetches a page by POST into the page buffer. * If there is no base for the URL then the * current base URL is used. After the fetch * the base URL reflects the new location. * @param string $url URL to fetch. * @param hash $parameters Optional additional GET data. * @return boolean/string Raw page on success. * @access public */ function post($url, $parameters = false) { return $this->failOnError($this->browser->post($url, $parameters)); } /** * Does a HTTP HEAD fetch, fetching only the page * headers. The current base URL is unchanged by this. * @param string $url URL to fetch. * @param hash $parameters Optional additional GET data. * @return boolean True on success. * @access public */ function head($url, $parameters = false) { return $this->failOnError($this->browser->head($url, $parameters)); } /** * Equivalent to hitting the retry button on the * browser. Will attempt to repeat the page fetch. * @return boolean True if fetch succeeded. * @access public */ function retry() { return $this->failOnError($this->browser->retry()); } /** * Equivalent to hitting the back button on the * browser. * @return boolean True if history entry and * fetch succeeded. * @access public */ function back() { return $this->failOnError($this->browser->back()); } /** * Equivalent to hitting the forward button on the * browser. * @return boolean True if history entry and * fetch succeeded. * @access public */ function forward() { return $this->failOnError($this->browser->forward()); } /** * Retries a request after setting the authentication * for the current realm. * @param string $username Username for realm. * @param string $password Password for realm. * @return boolean/string HTML on successful fetch. Note * that authentication may still have * failed. * @access public */ function authenticate($username, $password) { return $this->failOnError( $this->browser->authenticate($username, $password)); } /** * Gets the cookie value for the current browser context. * @param string $name Name of cookie. * @return string Value of cookie or false if unset. * @access public */ function getCookie($name) { return $this->browser->getCurrentCookieValue($name); } /** * Sets a cookie in the current browser. * @param string $name Name of cookie. * @param string $value Cookie value. * @param string $host Host upon which the cookie is valid. * @param string $path Cookie path if not host wide. * @param string $expiry Expiry date. * @access public */ function setCookie($name, $value, $host = false, $path = '/', $expiry = false) { $this->browser->setCookie($name, $value, $host, $path, $expiry); } /** * Accessor for current frame focus. Will be * false if no frame has focus. * @return integer/string/boolean Label if any, otherwise * the position in the frameset * or false if none. * @access public */ function getFrameFocus() { return $this->browser->getFrameFocus(); } /** * Sets the focus by index. The integer index starts from 1. * @param integer $choice Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocusByIndex($choice) { return $this->browser->setFrameFocusByIndex($choice); } /** * Sets the focus by name. * @param string $name Chosen frame. * @return boolean True if frame exists. * @access public */ function setFrameFocus($name) { return $this->browser->setFrameFocus($name); } /** * Clears the frame focus. All frames will be searched * for content. * @access public */ function clearFrameFocus() { return $this->browser->clearFrameFocus(); } /** * Clicks a visible text item. Will first try buttons, * then links and then images. * @param string $label Visible text or alt text. * @return string/boolean Raw page or false. * @access public */ function click($label) { return $this->failOnError($this->browser->click($label)); } /** * Checks for a click target. * @param string $label Visible text or alt text. * @return boolean True if click target. * @access public */ function assertClickable($label, $message = '%s') { return $this->assertTrue( $this->browser->isClickable($label), sprintf($message, "Click target [$label] should exist")); } /** * Clicks the submit button by label. The owning * form will be submitted by this. * @param string $label Button label. An unlabeled * button can be triggered by 'Submit'. * @param hash $additional Additional form values. * @return boolean/string Page on success, else false. * @access public */ function clickSubmit($label = 'Submit', $additional = false) { return $this->failOnError( $this->browser->clickSubmit($label, $additional)); } /** * Clicks the submit button by name attribute. The owning * form will be submitted by this. * @param string $name Name attribute of button. * @param hash $additional Additional form values. * @return boolean/string Page on success. * @access public */ function clickSubmitByName($name, $additional = false) { return $this->failOnError( $this->browser->clickSubmitByName($name, $additional)); } /** * Clicks the submit button by ID attribute. The owning * form will be submitted by this. * @param string $id ID attribute of button. * @param hash $additional Additional form values. * @return boolean/string Page on success. * @access public */ function clickSubmitById($id, $additional = false) { return $this->failOnError( $this->browser->clickSubmitById($id, $additional)); } /** * Checks for a valid button label. * @param string $label Visible text. * @return boolean True if click target. * @access public */ function assertSubmit($label, $message = '%s') { return $this->assertTrue( $this->browser->isSubmit($label), sprintf($message, "Submit button [$label] should exist")); } /** * Clicks the submit image by some kind of label. Usually * the alt tag or the nearest equivalent. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param string $label Alt attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form values. * @return boolean/string Page on success. * @access public */ function clickImage($label, $x = 1, $y = 1, $additional = false) { return $this->failOnError( $this->browser->clickImage($label, $x, $y, $additional)); } /** * Clicks the submit image by the name. Usually * the alt tag or the nearest equivalent. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param string $name Name attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form values. * @return boolean/string Page on success. * @access public */ function clickImageByName($name, $x = 1, $y = 1, $additional = false) { return $this->failOnError( $this->browser->clickImageByName($name, $x, $y, $additional)); } /** * Clicks the submit image by ID attribute. The owning * form will be submitted by this. Clicking outside of * the boundary of the coordinates will result in * a failure. * @param integer/string $id ID attribute of button. * @param integer $x X-coordinate of imaginary click. * @param integer $y Y-coordinate of imaginary click. * @param hash $additional Additional form values. * @return boolean/string Page on success. * @access public */ function clickImageById($id, $x = 1, $y = 1, $additional = false) { return $this->failOnError( $this->browser->clickImageById($id, $x, $y, $additional)); } /** * Checks for a valid image with atht alt text or title. * @param string $label Visible text. * @return boolean True if click target. * @access public */ function assertImage($label, $message = '%s') { return $this->assertTrue( $this->browser->isImage($label), sprintf($message, "Image with text [$label] should exist")); } /** * Submits a form by the ID. * @param string $id Form ID. No button information * is submitted this way. * @return boolean/string Page on success. * @access public */ function submitFormById($id) { return $this->failOnError($this->browser->submitFormById($id)); } /** * Follows a link by name. Will click the first link * found with this link text by default, or a later * one if an index is given. Match is case insensitive * with normalised space. * @param string $label Text between the anchor tags. * @param integer $index Link position counting from zero. * @return boolean/string Page on success. * @access public */ function clickLink($label, $index = 0) { return $this->failOnError($this->browser->clickLink($label, $index)); } /** * Follows a link by id attribute. * @param string $id ID attribute value. * @return boolean/string Page on success. * @access public */ function clickLinkById($id) { return $this->failOnError($this->browser->clickLinkById($id)); } /** * Tests for the presence of a link label. Match is * case insensitive with normalised space. * @param string $label Text between the anchor tags. * @param mixed $expected Expected URL or expectation object. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if link present. * @access public */ function assertLink($label, $expected = true, $message = '%s') { $url = $this->browser->getLink($label); if ($expected === true || ($expected !== true && $url === false)) { return $this->assertTrue($url !== false, sprintf($message, "Link [$label] should exist")); } if (! SimpleExpectation::isExpectation($expected)) { $expected = new IdenticalExpectation($expected); } return $this->assert($expected, $url->asString(), sprintf($message, "Link [$label] should match")); } /** * Tests for the non-presence of a link label. Match is * case insensitive with normalised space. * @param string/integer $label Text between the anchor tags * or ID attribute. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if link missing. * @access public */ function assertNoLink($label, $message = '%s') { return $this->assertTrue( $this->browser->getLink($label) === false, sprintf($message, "Link [$label] should not exist")); } /** * Tests for the presence of a link id attribute. * @param string $id Id attribute value. * @param mixed $expected Expected URL or expectation object. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if link present. * @access public */ function assertLinkById($id, $expected = true, $message = '%s') { $url = $this->browser->getLinkById($id); if ($expected === true) { return $this->assertTrue($url !== false, sprintf($message, "Link ID [$id] should exist")); } if (! SimpleExpectation::isExpectation($expected)) { $expected = new IdenticalExpectation($expected); } return $this->assert($expected, $url->asString(), sprintf($message, "Link ID [$id] should match")); } /** * Tests for the non-presence of a link label. Match is * case insensitive with normalised space. * @param string $id Id attribute value. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if link missing. * @access public */ function assertNoLinkById($id, $message = '%s') { return $this->assertTrue( $this->browser->getLinkById($id) === false, sprintf($message, "Link ID [$id] should not exist")); } /** * Sets all form fields with that label, or name if there * is no label attached. * @param string $name Name of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setField($label, $value, $position=false) { return $this->browser->setField($label, $value, $position); } /** * Sets all form fields with that name. * @param string $name Name of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setFieldByName($name, $value, $position=false) { return $this->browser->setFieldByName($name, $value, $position); } /** * Sets all form fields with that id. * @param string/integer $id Id of field in forms. * @param string $value New value of field. * @return boolean True if field exists, otherwise false. * @access public */ function setFieldById($id, $value) { return $this->browser->setFieldById($id, $value); } /** * Confirms that the form element is currently set * to the expected value. A missing form will always * fail. If no value is given then only the existence * of the field is checked. * @param string $name Name of field in forms. * @param mixed $expected Expected string/array value or * false for unset fields. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if pass. * @access public */ function assertField($label, $expected = true, $message = '%s') { $value = $this->browser->getField($label); return $this->assertFieldValue($label, $value, $expected, $message); } /** * Confirms that the form element is currently set * to the expected value. A missing form element will always * fail. If no value is given then only the existence * of the field is checked. * @param string $name Name of field in forms. * @param mixed $expected Expected string/array value or * false for unset fields. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if pass. * @access public */ function assertFieldByName($name, $expected = true, $message = '%s') { $value = $this->browser->getFieldByName($name); return $this->assertFieldValue($name, $value, $expected, $message); } /** * Confirms that the form element is currently set * to the expected value. A missing form will always * fail. If no ID is given then only the existence * of the field is checked. * @param string/integer $id Name of field in forms. * @param mixed $expected Expected string/array value or * false for unset fields. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if pass. * @access public */ function assertFieldById($id, $expected = true, $message = '%s') { $value = $this->browser->getFieldById($id); return $this->assertFieldValue($id, $value, $expected, $message); } /** * Tests the field value against the expectation. * @param string $identifier Name, ID or label. * @param mixed $value Current field value. * @param mixed $expected Expected value to match. * @param string $message Failure message. * @return boolean True if pass * @access protected */ protected function assertFieldValue($identifier, $value, $expected, $message) { if ($expected === true) { return $this->assertTrue( isset($value), sprintf($message, "Field [$identifier] should exist")); } if (! SimpleExpectation::isExpectation($expected)) { $identifier = str_replace('%', '%%', $identifier); $expected = new FieldExpectation( $expected, "Field [$identifier] should match with [%s]"); } return $this->assert($expected, $value, $message); } /** * Checks the response code against a list * of possible values. * @param array $responses Possible responses for a pass. * @param string $message Message to display. Default * can be embedded with %s. * @return boolean True if pass. * @access public */ function assertResponse($responses, $message = '%s') { $responses = (is_array($responses) ? $responses : array($responses)); $code = $this->browser->getResponseCode(); $message = sprintf($message, "Expecting response in [" . implode(", ", $responses) . "] got [$code]"); return $this->assertTrue(in_array($code, $responses), $message); } /** * Checks the mime type against a list * of possible values. * @param array $types Possible mime types for a pass. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertMime($types, $message = '%s') { $types = (is_array($types) ? $types : array($types)); $type = $this->browser->getMimeType(); $message = sprintf($message, "Expecting mime type in [" . implode(", ", $types) . "] got [$type]"); return $this->assertTrue(in_array($type, $types), $message); } /** * Attempt to match the authentication type within * the security realm we are currently matching. * @param string $authentication Usually basic. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertAuthentication($authentication = false, $message = '%s') { if (! $authentication) { $message = sprintf($message, "Expected any authentication type, got [" . $this->browser->getAuthentication() . "]"); return $this->assertTrue( $this->browser->getAuthentication(), $message); } else { $message = sprintf($message, "Expected authentication [$authentication] got [" . $this->browser->getAuthentication() . "]"); return $this->assertTrue( strtolower($this->browser->getAuthentication()) == strtolower($authentication), $message); } } /** * Checks that no authentication is necessary to view * the desired page. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertNoAuthentication($message = '%s') { $message = sprintf($message, "Expected no authentication type, got [" . $this->browser->getAuthentication() . "]"); return $this->assertFalse($this->browser->getAuthentication(), $message); } /** * Attempts to match the current security realm. * @param string $realm Name of security realm. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertRealm($realm, $message = '%s') { if (! SimpleExpectation::isExpectation($realm)) { $realm = new EqualExpectation($realm); } return $this->assert( $realm, $this->browser->getRealm(), "Expected realm -> $message"); } /** * Checks each header line for the required value. If no * value is given then only an existence check is made. * @param string $header Case insensitive header name. * @param mixed $value Case sensitive trimmed string to * match against. An expectation object * can be used for pattern matching. * @return boolean True if pass. * @access public */ function assertHeader($header, $value = false, $message = '%s') { return $this->assert( new HttpHeaderExpectation($header, $value), $this->browser->getHeaders(), $message); } /** * Confirms that the header type has not been received. * Only the landing page is checked. If you want to check * redirect pages, then you should limit redirects so * as to capture the page you want. * @param string $header Case insensitive header name. * @return boolean True if pass. * @access public */ function assertNoHeader($header, $message = '%s') { return $this->assert( new NoHttpHeaderExpectation($header), $this->browser->getHeaders(), $message); } /** * Tests the text between the title tags. * @param string/SimpleExpectation $title Expected title. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertTitle($title = false, $message = '%s') { if (! SimpleExpectation::isExpectation($title)) { $title = new EqualExpectation($title); } return $this->assert($title, $this->browser->getTitle(), $message); } /** * Will trigger a pass if the text is found in the plain * text form of the page. * @param string $text Text to look for. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertText($text, $message = '%s') { return $this->assert( new TextExpectation($text), $this->browser->getContentAsText(), $message); } /** * Will trigger a pass if the text is not found in the plain * text form of the page. * @param string $text Text to look for. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertNoText($text, $message = '%s') { return $this->assert( new NoTextExpectation($text), $this->browser->getContentAsText(), $message); } /** * Will trigger a pass if the Perl regex pattern * is found in the raw content. * @param string $pattern Perl regex to look for including * the regex delimiters. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertPattern($pattern, $message = '%s') { return $this->assert( new PatternExpectation($pattern), $this->browser->getContent(), $message); } /** * Will trigger a pass if the perl regex pattern * is not present in raw content. * @param string $pattern Perl regex to look for including * the regex delimiters. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertNoPattern($pattern, $message = '%s') { return $this->assert( new NoPatternExpectation($pattern), $this->browser->getContent(), $message); } /** * Checks that a cookie is set for the current page * and optionally checks the value. * @param string $name Name of cookie to test. * @param string $expected Expected value as a string or * false if any value will do. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertCookie($name, $expected = false, $message = '%s') { $value = $this->getCookie($name); if (! $expected) { return $this->assertTrue( $value, sprintf($message, "Expecting cookie [$name]")); } if (! SimpleExpectation::isExpectation($expected)) { $expected = new EqualExpectation($expected); } return $this->assert($expected, $value, "Expecting cookie [$name] -> $message"); } /** * Checks that no cookie is present or that it has * been successfully cleared. * @param string $name Name of cookie to test. * @param string $message Message to display. * @return boolean True if pass. * @access public */ function assertNoCookie($name, $message = '%s') { return $this->assertTrue( $this->getCookie($name) === null or $this->getCookie($name) === false, sprintf($message, "Not expecting cookie [$name]")); } /** * Called from within the test methods to register * passes and failures. * @param boolean $result Pass on true. * @param string $message Message to display describing * the test state. * @return boolean True on pass * @access public */ function assertTrue($result, $message = false) { return $this->assert(new TrueExpectation(), $result, $message); } /** * Will be true on false and vice versa. False * is the PHP definition of false, so that null, * empty strings, zero and an empty array all count * as false. * @param boolean $result Pass on false. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertFalse($result, $message = '%s') { return $this->assert(new FalseExpectation(), $result, $message); } /** * Will trigger a pass if the two parameters have * the same value only. Otherwise a fail. This * is for testing hand extracted text, etc. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertEqual($first, $second, $message = '%s') { return $this->assert( new EqualExpectation($first), $second, $message); } /** * Will trigger a pass if the two parameters have * a different value. Otherwise a fail. This * is for testing hand extracted text, etc. * @param mixed $first Value to compare. * @param mixed $second Value to compare. * @param string $message Message to display. * @return boolean True on pass * @access public */ function assertNotEqual($first, $second, $message = '%s') { return $this->assert( new NotEqualExpectation($first), $second, $message); } /** * Uses a stack trace to find the line of an assertion. * @return string Line number of first assert* * method embedded in format string. * @access public */ function getAssertionLine() { $trace = new SimpleStackTrace(array('assert', 'click', 'pass', 'fail')); return $trace->traceMethod(); } } ?>Swift-4.2.1/test-suite/lib/simpletest/xml.php100644 0 0 46410 12000050366 16334 0ustar 0 0 namespace = ($namespace ? $namespace . ':' : ''); $this->indent = $indent; } /** * Calculates the pretty printing indent level * from the current level of nesting. * @param integer $offset Extra indenting level. * @return string Leading space. * @access protected */ protected function getIndent($offset = 0) { return str_repeat( $this->indent, count($this->getTestList()) + $offset); } /** * Converts character string to parsed XML * entities string. * @param string text Unparsed character data. * @return string Parsed character data. * @access public */ function toParsedXml($text) { return str_replace( array('&', '<', '>', '"', '\''), array('&', '<', '>', '"', '''), $text); } /** * Paints the start of a group test. * @param string $test_name Name of test that is starting. * @param integer $size Number of test cases starting. * @access public */ function paintGroupStart($test_name, $size) { parent::paintGroupStart($test_name, $size); print $this->getIndent(); print "<" . $this->namespace . "group size=\"$size\">\n"; print $this->getIndent(1); print "<" . $this->namespace . "name>" . $this->toParsedXml($test_name) . "namespace . "name>\n"; } /** * Paints the end of a group test. * @param string $test_name Name of test that is ending. * @access public */ function paintGroupEnd($test_name) { print $this->getIndent(); print "namespace . "group>\n"; parent::paintGroupEnd($test_name); } /** * Paints the start of a test case. * @param string $test_name Name of test that is starting. * @access public */ function paintCaseStart($test_name) { parent::paintCaseStart($test_name); print $this->getIndent(); print "<" . $this->namespace . "case>\n"; print $this->getIndent(1); print "<" . $this->namespace . "name>" . $this->toParsedXml($test_name) . "namespace . "name>\n"; } /** * Paints the end of a test case. * @param string $test_name Name of test that is ending. * @access public */ function paintCaseEnd($test_name) { print $this->getIndent(); print "namespace . "case>\n"; parent::paintCaseEnd($test_name); } /** * Paints the start of a test method. * @param string $test_name Name of test that is starting. * @access public */ function paintMethodStart($test_name) { parent::paintMethodStart($test_name); print $this->getIndent(); print "<" . $this->namespace . "test>\n"; print $this->getIndent(1); print "<" . $this->namespace . "name>" . $this->toParsedXml($test_name) . "namespace . "name>\n"; } /** * Paints the end of a test method. * @param string $test_name Name of test that is ending. * @param integer $progress Number of test cases ending. * @access public */ function paintMethodEnd($test_name) { print $this->getIndent(); print "namespace . "test>\n"; parent::paintMethodEnd($test_name); } /** * Paints pass as XML. * @param string $message Message to encode. * @access public */ function paintPass($message) { parent::paintPass($message); print $this->getIndent(1); print "<" . $this->namespace . "pass>"; print $this->toParsedXml($message); print "namespace . "pass>\n"; } /** * Paints failure as XML. * @param string $message Message to encode. * @access public */ function paintFail($message) { parent::paintFail($message); print $this->getIndent(1); print "<" . $this->namespace . "fail>"; print $this->toParsedXml($message); print "namespace . "fail>\n"; } /** * Paints error as XML. * @param string $message Message to encode. * @access public */ function paintError($message) { parent::paintError($message); print $this->getIndent(1); print "<" . $this->namespace . "exception>"; print $this->toParsedXml($message); print "namespace . "exception>\n"; } /** * Paints exception as XML. * @param Exception $exception Exception to encode. * @access public */ function paintException($exception) { parent::paintException($exception); print $this->getIndent(1); print "<" . $this->namespace . "exception>"; $message = 'Unexpected exception of type [' . get_class($exception) . '] with message ['. $exception->getMessage() . '] in ['. $exception->getFile() . ' line ' . $exception->getLine() . ']'; print $this->toParsedXml($message); print "namespace . "exception>\n"; } /** * Paints the skipping message and tag. * @param string $message Text to display in skip tag. * @access public */ function paintSkip($message) { parent::paintSkip($message); print $this->getIndent(1); print "<" . $this->namespace . "skip>"; print $this->toParsedXml($message); print "namespace . "skip>\n"; } /** * Paints a simple supplementary message. * @param string $message Text to display. * @access public */ function paintMessage($message) { parent::paintMessage($message); print $this->getIndent(1); print "<" . $this->namespace . "message>"; print $this->toParsedXml($message); print "namespace . "message>\n"; } /** * Paints a formatted ASCII message such as a * privateiable dump. * @param string $message Text to display. * @access public */ function paintFormattedMessage($message) { parent::paintFormattedMessage($message); print $this->getIndent(1); print "<" . $this->namespace . "formatted>"; print ""; print "namespace . "formatted>\n"; } /** * Serialises the event object. * @param string $type Event type as text. * @param mixed $payload Message or object. * @access public */ function paintSignal($type, $payload) { parent::paintSignal($type, $payload); print $this->getIndent(1); print "<" . $this->namespace . "signal type=\"$type\">"; print ""; print "namespace . "signal>\n"; } /** * Paints the test document header. * @param string $test_name First test top level * to start. * @access public * @abstract */ function paintHeader($test_name) { if (! SimpleReporter::inCli()) { header('Content-type: text/xml'); } print "namespace) { print " xmlns:" . $this->namespace . "=\"www.lastcraft.com/SimpleTest/Beta3/Report\""; } print "?>\n"; print "<" . $this->namespace . "run>\n"; } /** * Paints the test document footer. * @param string $test_name The top level test. * @access public * @abstract */ function paintFooter($test_name) { print "namespace . "run>\n"; } } /** * Accumulator for incoming tag. Holds the * incoming test structure information for * later dispatch to the reporter. * @package SimpleTest * @subpackage UnitTester */ class NestingXmlTag { private $name; private $attributes; /** * Sets the basic test information except * the name. * @param hash $attributes Name value pairs. * @access public */ function NestingXmlTag($attributes) { $this->name = false; $this->attributes = $attributes; } /** * Sets the test case/method name. * @param string $name Name of test. * @access public */ function setName($name) { $this->name = $name; } /** * Accessor for name. * @return string Name of test. * @access public */ function getName() { return $this->name; } /** * Accessor for attributes. * @return hash All attributes. * @access protected */ protected function getAttributes() { return $this->attributes; } } /** * Accumulator for incoming method tag. Holds the * incoming test structure information for * later dispatch to the reporter. * @package SimpleTest * @subpackage UnitTester */ class NestingMethodTag extends NestingXmlTag { /** * Sets the basic test information except * the name. * @param hash $attributes Name value pairs. * @access public */ function NestingMethodTag($attributes) { $this->NestingXmlTag($attributes); } /** * Signals the appropriate start event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintStart(&$listener) { $listener->paintMethodStart($this->getName()); } /** * Signals the appropriate end event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintEnd(&$listener) { $listener->paintMethodEnd($this->getName()); } } /** * Accumulator for incoming case tag. Holds the * incoming test structure information for * later dispatch to the reporter. * @package SimpleTest * @subpackage UnitTester */ class NestingCaseTag extends NestingXmlTag { /** * Sets the basic test information except * the name. * @param hash $attributes Name value pairs. * @access public */ function NestingCaseTag($attributes) { $this->NestingXmlTag($attributes); } /** * Signals the appropriate start event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintStart(&$listener) { $listener->paintCaseStart($this->getName()); } /** * Signals the appropriate end event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintEnd(&$listener) { $listener->paintCaseEnd($this->getName()); } } /** * Accumulator for incoming group tag. Holds the * incoming test structure information for * later dispatch to the reporter. * @package SimpleTest * @subpackage UnitTester */ class NestingGroupTag extends NestingXmlTag { /** * Sets the basic test information except * the name. * @param hash $attributes Name value pairs. * @access public */ function NestingGroupTag($attributes) { $this->NestingXmlTag($attributes); } /** * Signals the appropriate start event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintStart(&$listener) { $listener->paintGroupStart($this->getName(), $this->getSize()); } /** * Signals the appropriate end event on the * listener. * @param SimpleReporter $listener Target for events. * @access public */ function paintEnd(&$listener) { $listener->paintGroupEnd($this->getName()); } /** * The size in the attributes. * @return integer Value of size attribute or zero. * @access public */ function getSize() { $attributes = $this->getAttributes(); if (isset($attributes['SIZE'])) { return (integer)$attributes['SIZE']; } return 0; } } /** * Parser for importing the output of the XmlReporter. * Dispatches that output to another reporter. * @package SimpleTest * @subpackage UnitTester */ class SimpleTestXmlParser { private $listener; private $expat; private $tag_stack; private $in_content_tag; private $content; private $attributes; /** * Loads a listener with the SimpleReporter * interface. * @param SimpleReporter $listener Listener of tag events. * @access public */ function SimpleTestXmlParser(&$listener) { $this->listener = &$listener; $this->expat = &$this->createParser(); $this->tag_stack = array(); $this->in_content_tag = false; $this->content = ''; $this->attributes = array(); } /** * Parses a block of XML sending the results to * the listener. * @param string $chunk Block of text to read. * @return boolean True if valid XML. * @access public */ function parse($chunk) { if (! xml_parse($this->expat, $chunk)) { trigger_error('XML parse error with ' . xml_error_string(xml_get_error_code($this->expat))); return false; } return true; } /** * Sets up expat as the XML parser. * @return resource Expat handle. * @access protected */ protected function &createParser() { $expat = xml_parser_create(); xml_set_object($expat, $this); xml_set_element_handler($expat, 'startElement', 'endElement'); xml_set_character_data_handler($expat, 'addContent'); xml_set_default_handler($expat, 'defaultContent'); return $expat; } /** * Opens a new test nesting level. * @return NestedXmlTag The group, case or method tag * to start. * @access private */ protected function pushNestingTag($nested) { array_unshift($this->tag_stack, $nested); } /** * Accessor for current test structure tag. * @return NestedXmlTag The group, case or method tag * being parsed. * @access private */ protected function &getCurrentNestingTag() { return $this->tag_stack[0]; } /** * Ends a nesting tag. * @return NestedXmlTag The group, case or method tag * just finished. * @access private */ protected function popNestingTag() { return array_shift($this->tag_stack); } /** * Test if tag is a leaf node with only text content. * @param string $tag XML tag name. * @return @boolean True if leaf, false if nesting. * @private */ protected function isLeaf($tag) { return in_array($tag, array( 'NAME', 'PASS', 'FAIL', 'EXCEPTION', 'SKIP', 'MESSAGE', 'FORMATTED', 'SIGNAL')); } /** * Handler for start of event element. * @param resource $expat Parser handle. * @param string $tag Element name. * @param hash $attributes Name value pairs. * Attributes without content * are marked as true. * @access protected */ protected function startElement($expat, $tag, $attributes) { $this->attributes = $attributes; if ($tag == 'GROUP') { $this->pushNestingTag(new NestingGroupTag($attributes)); } elseif ($tag == 'CASE') { $this->pushNestingTag(new NestingCaseTag($attributes)); } elseif ($tag == 'TEST') { $this->pushNestingTag(new NestingMethodTag($attributes)); } elseif ($this->isLeaf($tag)) { $this->in_content_tag = true; $this->content = ''; } } /** * End of element event. * @param resource $expat Parser handle. * @param string $tag Element name. * @access protected */ protected function endElement($expat, $tag) { $this->in_content_tag = false; if (in_array($tag, array('GROUP', 'CASE', 'TEST'))) { $nesting_tag = $this->popNestingTag(); $nesting_tag->paintEnd($this->listener); } elseif ($tag == 'NAME') { $nesting_tag = &$this->getCurrentNestingTag(); $nesting_tag->setName($this->content); $nesting_tag->paintStart($this->listener); } elseif ($tag == 'PASS') { $this->listener->paintPass($this->content); } elseif ($tag == 'FAIL') { $this->listener->paintFail($this->content); } elseif ($tag == 'EXCEPTION') { $this->listener->paintError($this->content); } elseif ($tag == 'SKIP') { $this->listener->paintSkip($this->content); } elseif ($tag == 'SIGNAL') { $this->listener->paintSignal( $this->attributes['TYPE'], unserialize($this->content)); } elseif ($tag == 'MESSAGE') { $this->listener->paintMessage($this->content); } elseif ($tag == 'FORMATTED') { $this->listener->paintFormattedMessage($this->content); } } /** * Content between start and end elements. * @param resource $expat Parser handle. * @param string $text Usually output messages. * @access protected */ protected function addContent($expat, $text) { if ($this->in_content_tag) { $this->content .= $text; } return true; } /** * XML and Doctype handler. Discards all such content. * @param resource $expat Parser handle. * @param string $default Text of default content. * @access protected */ protected function defaultContent($expat, $default) { } } ?> Swift-4.2.1/test-suite/lib/yaymock/classes/Yay.php100644 0 0 14451 12000050366 17216 0ustar 0 0 . */ //require 'Yay/Expectations.php'; //require 'Yay/Matchers/OptionalMatcher.php'; //require 'Yay/Matchers/AnyMatcher.php'; //require 'Yay/Matchers/IdenticalMatcher.php'; //require 'Yay/Matchers/EqualMatcher.php'; //require 'Yay/Matchers/PatternMatcher.php'; //require 'Yay/Matchers/ReferenceMatcher.php'; //require 'Yay/Matchers/BoundsMatcher.php'; //require 'Yay/Actions/ReturnValueAction.php'; //require 'Yay/Actions/ReturnReferenceAction.php'; //require 'Yay/Actions/ThrowAction.php'; //require 'Yay/Actions/CallbackAction.php'; /** * A convenience factory class. * @author Chris Corbyn * @package Yay */ class Yay { /** * The classpath used for autoloading. * @var string * @access private */ private static $CLASSPATH = '.'; // -- Expectations /** * Create a new Expectations builder instance. * @return Yay_Expectations */ public static function expectations() { return new Yay_Expectations(); } // -- Matchers /** * Create a new Optional matcher, optionally wrapping $value. * @param string $value, optional * @return Yay_Matchers_OptionalMatcher */ public static function optional($value = null) { return new Yay_Matchers_OptionalMatcher($value); } /** * Create a new Any matcher, optionally constrained to $type. * @param string $type, optional * @return Yay_Matchers_AnyMatcher */ public static function any($type = null) { return new Yay_Matchers_AnyMatcher($type, true); } /** * Create a negated Any matcher, optionally constrained to $type. * @param string $type, optional * @return Yay_Matchers_AnyMatcher */ public static function none($type = null) { return new Yay_Matchers_AnyMatcher($type, false); } /** * Create a new Identical matcher for $value. * @param mixed $value * @return Yay_Matchers_IdenticalMatcher */ public static function identical($value) { return new Yay_Matchers_IdenticalMatcher($value, true); } /** * Create a negated Identical matcher for $value. * @param mixed $value * @return Yay_Matchers_IdenticalMatcher */ public static function notIdentical($value) { return new Yay_Matchers_IdenticalMatcher($value, false); } /** * Create a new Equal matcher for $value. * @param mixed $value * @return Yay_Matchers_EqualMatcher */ public static function equal($value) { return new Yay_Matchers_EqualMatcher($value, true); } /** * Create a negated Equal matcher for $value. * @param mixed $value * @return Yay_Matchers_EqualMatcher */ public static function notEqual($value) { return new Yay_Matchers_EqualMatcher($value, false); } /** * Create a new Pattern matcher for $pattern. * @param string $pattern * @return Yay_Matchers_IsAMatcher */ public static function pattern($pattern) { return new Yay_Matchers_PatternMatcher($pattern, true); } /** * Create a negated Pattern matcher for $pattern. * @param string $pattern * @return Yay_Matchers_IsAMatcher */ public static function noPattern($pattern) { return new Yay_Matchers_PatternMatcher($pattern, false); } /** * Create a new Reference matcher for $ref. * @param mixed $ref * @return Yay_Matchers_ReferenceMatcher */ public static function reference(&$ref) { return new Yay_Matchers_ReferenceMatcher($ref, true); } /** * Create a negated Reference matcher for $ref. * @param mixed $ref * @return Yay_Matchers_ReferenceMatcher */ public static function noReference(&$ref) { return new Yay_Matchers_ReferenceMatcher($ref, false); } /** * Create a new Bounds matcher for boundaries between $lower and $upper. * @param mixed $lower * @param mixed $upper * @return Yay_Matchers_BoundsMatcher */ public static function bounds($lower, $upper) { return new Yay_Matchers_BoundsMatcher($lower, $upper, true); } /** * Create a negated Bounds matcher for boundaries outside $lower and $upper. * @param mixed $lower * @param mixed $upper * @return Yay_Matchers_BoundsMatcher */ public static function outside($lower, $upper) { return new Yay_Matchers_BoundsMatcher($lower, $upper, false); } // -- Actions /** * Create a new ReturnValueAction with $value. * @param mixed $value * @return Yay_Actions_ReturnValueAction */ public static function returnValue($value) { return new Yay_Actions_ReturnValueAction($value); } /** * Create a new ReturnReferenceAction with &$ref. * @param mixed $ref * @return Yay_Actions_ReturnReferenceAction */ public static function returnReference(&$ref) { return new Yay_Actions_ReturnReferenceAction($ref); } /** * Create a new ThrowAction with $e. * @param Exception $ref * @return Yay_Actions_ThrowAction */ public static function throwException(Exception $e) { return new Yay_Actions_ThrowAction($e); } /** * Create a new CallbackAction with $callback. * @param callback $callback * @return Yay_Actions_CallbackAction */ public static function call($callback) { return new Yay_Actions_CallbackAction($callback); } /** * Set the classpath for autoloading. * @param string $path */ public static function setClassPath($path) { self::$CLASSPATH = $path; } /** * Static autoloader registered in bootstrap file. * @param string $class */ public static function autoload($class) { if (substr($class, 0, 3) != 'Yay') { return; } $file = str_replace('_', '/', $class) . '.php'; $path = self::$CLASSPATH . '/' . $file; if (is_file($path)) { require_once $path; } } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Action.php100644 0 0 2064 12000050366 20410 0ustar 0 0 . */ //require 'Yay/Invocation.php'; //require 'Yay/SelfDescribing.php'; /** * An Action performed when an expected Invocation occurs. * @author Chris Corbyn * @package Yay */ interface Yay_Action extends Yay_SelfDescribing { /** * Mimmick the method Invocation and return a value. * @param Yay_Invocation $invocation * @return mixed */ public function &invoke(Yay_Invocation $invocation); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Actions/CallbackAction.php100644 0 0 3161 12000050366 23424 0ustar 0 0 . */ //require 'Yay/Action.php'; //require 'Yay/Description.php'; /** * An Action which delegates to a callback. * @author Chris Corbyn * @package Yay */ class Yay_Actions_CallbackAction implements Yay_Action { /** * The callback to invoke. * @var callback * @access private */ private $_callback; /** * Create a new CallbackAction for $callback. * @param callback $callback */ public function __construct($callback) { $this->_callback = $callback; } /** * Mimmick the method Invocation and return a value. * @param Yay_Invocation $invocation * @return mixed */ public function &invoke(Yay_Invocation $invocation) { $ret = call_user_func($this->_callback, $invocation); return $ret; } /** * Describe this Expectation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(' Runs a callback;'); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Actions/ReturnReferenceAction.php100644 0 0 3021 12000050366 25021 0ustar 0 0 . */ //require 'Yay/Action.php'; /** * An Action which returns a reference. * @author Chris Corbyn * @package Yay */ class Yay_Actions_ReturnReferenceAction implements Yay_Action { /** * The reference to return. * @var mixed * @access private */ private $_ref; /** * Create a new ReturnReferenceAction for &$ref. * @param mixed $ref */ public function __construct(&$ref) { $this->_ref =& $ref; } /** * Mimmick the method Invocation and return the reference. * @param Yay_Invocation $invocation * @return mixed */ public function &invoke(Yay_Invocation $invocation) { return $this->_ref; } /** * Describe this Expectation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(' Returns a reference;'); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Actions/ReturnValueAction.php100644 0 0 5043 12000050366 24205 0ustar 0 0 . */ //require 'Yay/Action.php'; /** * An Action which returns a specified value. * @author Chris Corbyn * @package Yay */ class Yay_Actions_ReturnValueAction implements Yay_Action { /** * The value to return. * @var mixed * @access private */ private $_value; /** * Create a new ReturnValueAction for $value. * @param mixed $value */ public function __construct($value) { $this->_value = $value; } /** * Mimmick the method Invocation and return a value. * @param Yay_Invocation $invocation * @return mixed */ public function &invoke(Yay_Invocation $invocation) { $value = $this->_value; return $value; } /** * Describe this Expectation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(sprintf(' Returns %s;', $this->_describeValue('%s [%s]'))); } private function _describeValue($format) { $description = ''; $value = $this->_value; if (is_int($value)) { $description = sprintf($format, 'int', $value); } elseif (is_float($value)) { $description = sprintf($format, 'float', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_numeric($value)) { $description = sprintf($format, 'number', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_string($value)) { $description = sprintf($format, 'string', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_object($value)) { $description = sprintf($format, 'object', get_class($value)); } elseif (is_array($value)) { $description = sprintf($format, 'array', count($value) . ' items'); } else { $description = sprintf($format, gettype($value), preg_replace('/^(.{8}).+/', '$1..', (string) $value)); } return $description; } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Actions/ThrowAction.php100644 0 0 3041 12000050366 23030 0ustar 0 0 . */ //require 'Yay/Action.php'; /** * An Action which throws an Exception. * @author Chris Corbyn * @package Yay */ class Yay_Actions_ThrowAction implements Yay_Action { /** * The Exception to throw. * @var Exception * @access private */ private $_e; /** * Create a new ThrowAction for $e. * @param Exception $e */ public function __construct(Exception $e) { $this->_e = $e; } /** * Mimmick the method Invocation and throw an Exception. * @param Yay_Invocation $invocation * @throws Exception */ public function &invoke(Yay_Invocation $invocation) { throw $this->_e; } /** * Describe this Expectation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText( sprintf(' Throws %s;', get_class($this->_e)) ); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Description.php100644 0 0 2260 12000050366 21454 0ustar 0 0 . */ /** * A Description container for error messages. * @author Chris Corbyn * @package Yay */ interface Yay_Description { /** * Append an existing Description to this Description. * @param Yay_Description */ public function appendDescription(Yay_Description $description); /** * Append text content to this Description. * @param string $text */ public function appendText($text); /** * Get this description back as a formatted string. * @return string */ public function toString(); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectation.php100644 0 0 4643 12000050366 21463 0ustar 0 0 . */ //require 'Yay/MockObject.php'; //require 'Yay/Invocation.php'; //require 'Yay/Action.php'; //require 'Yay/SelfDescribing.php'; //require 'Yay/State.php'; //require 'Yay/StatePredicate.php'; //require 'Yay/Sequence.php'; /** * An Invocation expectation. * @author Chris Corbyn * @package Yay */ interface Yay_Expectation extends Yay_SelfDescribing { /** * Specify the MockObject which the Invocation will occur. * This method should return the mock object in record mode. * @param Yay_MockObject $mock * @return Yay_MockObject */ public function of(Yay_MockObject $mock); /** * Notify the Expectation of an Invocation and check if it matches. * @param Yay_Invocation $invocation * @return boolean */ public function isExpected(Yay_Invocation $invocation); /** * Specify the Action to run if a match occurs. * @param Yay_Action $action */ public function will(Yay_Action $action); /** * Only be expected when in the given State predicate. * @param Yay_StatePredicate $predicate */ public function when(Yay_StatePredicate $predicate); /** * Activate the given $state if a match occurs. * @param Yay_State $state */ public function then(Yay_State $state); /** * Constrain this expectation to be valid only if invoked in the given sequence. * @param Yay_Sequence $sequence */ public function inSequence(Yay_Sequence $sequence); /** * Test if all conditions of the Invocation are satisfied. * @return boolean */ public function isSatisfied(); /** * Get the Action for the given Invocation. * This may have been specified by a will() clause. * @param Yay_Invocation $invocation * @return Yay_Action */ public function getAction(Yay_Invocation $invocation); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/ExpectationProvider.php100644 0 0 1620 12000050366 23166 0ustar 0 0 . */ /** * An Invocation expectation provider. * @author Chris Corbyn * @package Yay */ interface Yay_ExpectationProvider { /** * Returns the Expectations. * @return array of Yay_Expectation */ public function getExpectations(); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations.php100644 0 0 17507 12000050366 21671 0ustar 0 0 . */ //require 'Yay/Expectation.php'; //require 'Yay/InvocationRecorder.php'; //require 'Yay/InvocationProxy.php'; //require 'Yay/Invocation.php'; //require 'Yay/State.php'; //require 'Yay/StatePredicate.php'; //require 'Yay/Sequence.php'; //require 'Yay/Expectations/ExactlyExpectation.php'; //require 'Yay/Expectations/AtLeastExpectation.php'; //require 'Yay/Expectations/AtMostExpectation.php'; //require 'Yay/Expectations/BetweenExpectation.php'; //require 'Yay/Action.php'; //require 'Yay/Actions/ReturnValueAction.php'; //require 'Yay/Actions/ReturnReferenceAction.php'; //require 'Yay/Actions/ThrowAction.php'; //require 'Yay/Actions/CallbackAction.php'; /** * A group of expectations which can be specified in a fluid manner. * Generally speaking this is where all expectations should be made for the sake * of abstraction. * @author Chris Corbyn * @package Yay */ class Yay_Expectations implements Yay_InvocationRecorder { /** * The Expectation stack. * @var array * @access private */ private $_expectations = array(); /** * The current Expectation to proxy any recording to. * @var Yay_Expectation * @access private */ private $_currentEndpoint; /** * Create a new instance of Expectations. * @return Yay_Expectations */ final public static function create() { return new self(); } /** * Expect one Invocation on the $mock object. * Returns the mock object in record mode. * @param Yay_MockObject $mock * @return Yay_Expectations */ public function one(Yay_MockObject $mock) { return $this->exactly(1)->of($mock); } /** * Expect exactly $n Invocations on a mock object specified with a following * of() clause. * Example: Expectations::create()->exactly(2)->of($mock); * @param int $n * @return Yay_Expectations */ public function exactly($n) { return $this->_setEndpoint(new Yay_Expectations_ExactlyExpectation($n)); } /** * Expect at least $n Invocations on a mock object specified with a following * of() clause. * Example: Expectations::create()->atLeast(2)->of($mock); * @param int $n * @return Yay_Expectations */ public function atLeast($n) { return $this->_setEndpoint(new Yay_Expectations_AtLeastExpectation($n)); } /** * Expect at most $n Invocations on a mock object specified with a following * of() clause. * Example: Expectations::create()->atMost(2)->of($mock); * @param int $n * @return Yay_Expectations */ public function atMost($n) { return $this->_setEndpoint(new Yay_Expectations_AtMostExpectation($n)); } /** * Expect at between $min and $max Invocations on a mock object specified * with a following of() clause. * Example: Expectations::create()->atLeast(2)->of($mock); * @param int $n * @return Yay_Expectations */ public function between($min, $max) { return $this->_setEndpoint(new Yay_Expectations_BetweenExpectation($min, $max)); } /** * Ignore Invocations on the $mock object specified. * @param Yay_MockObject $mock * @return Yay_Expectations */ public function ignoring(Yay_MockObject $mock) { return $this->atLeast(0)->of($mock); } /** * Allow Invocations on the $mock object specified. * This does exactly the same thing as ignoring() but it allows a semantically * different meaning in the test case. * @param Yay_MockObject $mock * @return Yay_Expectations */ public function allowing(Yay_MockObject $mock) { return $this->ignoring($mock); } /** * Deny Invocations on the $mock object specified. * @param Yay_MockObject $mock * @return Yay_Expectations */ public function never(Yay_MockObject $mock) { return $this->exactly(0)->of($mock); } /** * Specify the MockObject which the Invocation will occur. * This method returns the mock object in record mode. * @param Yay_MockObject $mock * @return Yay_InvocationProxy */ public function of(Yay_MockObject $mock) { $this->_getEndpoint()->of($mock); return new Yay_InvocationProxy($this, $mock); } /** * Specify the Action to run if a match occurs. * @param Yay_Action $action */ public function will(Yay_Action $action) { $this->_getEndpoint()->will($action); return $this; } /** * Only be expected when in the given State predicate. * @param Yay_StatePredicate $predicate */ public function when(Yay_StatePredicate $predicate) { $this->_getEndpoint()->when($predicate); return $this; } /** * Activate the given $state if a match occurs. * @param Yay_State $state */ public function then(Yay_State $state) { $this->_getEndpoint()->then($state); return $this; } /** * Constrain the current expectation to occur in the given sequence. * @param Yay_Sequence $seq */ public function inSequence(Yay_Sequence $seq) { $this->_getEndpoint()->inSequence($seq); return $this; } /** * A wrapper for will(Yay::returnValue($value)). * @param mixed $value */ public function returns($value) { $this->_getEndpoint()->will(new Yay_Actions_ReturnValueAction($value)); return $this; } /** * A wrapper for will(Yay::returnReference($ref)). * @param mixed $ref */ public function returnsReference(&$ref) { $this->_getEndpoint()->will(new Yay_Actions_ReturnReferenceAction($ref)); return $this; } /** * A wrapper for will(Yay::throwException($e)). * @param Exception $e */ public function throws(Exception $e) { $this->_getEndpoint()->will(new Yay_Actions_ThrowAction($e)); return $this; } /** * A wrapper for will(Yay::call($callback)). * @param callback $callback */ public function calls($callback) { $this->_getEndpoint()->will(new Yay_Actions_CallbackAction($callback)); return $this; } /** * Record any Invocations on the MockObject whilst it's in record mode. * @param Yay_Invocation $invocation */ public function recordInvocation(Yay_Invocation $invocation) { $this->_getEndpoint()->recordInvocation($invocation); } /** * Returns the Expectation stack. * @return Yay_Expectation */ public function getExpectations() { return $this->_expectations; } // -- Private methods /** * Apply a new Expectation to the stack and tag it as the endpoint for recording. * @param Yay_Expectation $expectation * @return Yay_Expectations * @access private */ private function _setEndpoint(Yay_Expectation $expectation) { $this->_expectations[] = $expectation; $this->_currentEndpoint = $expectation; return $this; } /** * Gets the current endpoint (current expectation). * @return Yay_Expectation * @access private */ private function _getEndpoint() { if (!isset($this->_currentEndpoint)) { throw new BadMethodCallException( 'No cardinality clause has yet been made. First call one(), atLeast(), ' . 'atMost(), exactly(), between(), ignoring(), allowing() or never() ' . 'before performing this operation.' ); } else { return $this->_currentEndpoint; } } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/AbstractExpectation.php100644 0 0 17663 12000050366 25643 0ustar 0 0 . */ //require 'Yay/Mockery.php'; //require 'Yay/Expectation.php'; //require 'Yay/ExpectationProvider.php'; //require 'Yay/Invocation.php'; //require 'Yay/InvocationRecorder.php'; //require 'Yay/InvocationProxy.php'; //require 'Yay/Action.php'; //require 'Yay/Matcher.php'; //require 'Yay/Matchers/IdenticalMatcher.php'; //require 'Yay/State.php'; //require 'Yay/StatePredicate.php'; //require 'Yay/Sequence.php'; //require 'Yay/Description.php'; //require 'Yay/MockGenerator.php'; /** * A base Expectation which other Expectations extend. * @author Chris Corbyn * @package Yay */ abstract class Yay_Expectations_AbstractExpectation implements Yay_Expectation, Yay_InvocationRecorder { /** * The object to expect Invocations from. * @var Yay_MockObject * @access private */ private $_object; /** * The method name to expect Invocations on. * @var string * @access private */ private $_method; /** * The argument Matchers. * @var array * @access private */ private $_matchers = array(); /** * The Action to use if matched. * @var Yay_Action * @access private */ private $_action; /** * A state predicate to check for. * @var Yay_StatePredicate * @access private */ private $_statePredicate; /** * A state to effect if matched. * @var Yay_State * @access private */ private $_state; /** * The ID wanted to be valid in the Sequence. * @var int * @access private */ private $_wantedSequenceId; /** * The Sequence to check for validity (if any). * @var Yay_Sequence * @access private */ private $_sequence; /** * Invoked when the expectation matches so any counters can be incremented * for example. * @param Yay_Invocation $invocation */ abstract public function notifyMatchedInvocation(Yay_Invocation $invocation); /** * Describe the boundaries of how many invocations can occur. * @param Yay_Description $description */ abstract public function describeBounds(Yay_Description $description); /** * Describe the current status of this expectation. * @param Yay_Description $description */ abstract public function describeSatisfaction(Yay_Description $description); /** * Specify the MockObject which the Invocation will occur. * This method returns the mock object in record mode. * @param Yay_MockObject $mock * @return Yay_InvocationProxy */ public function of(Yay_MockObject $mock) { $this->_object = $mock; return new Yay_InvocationProxy($this, $mock); } /** * Notify the Expectation of an Invocation and check if it matches. * @param Yay_Invocation $invocation * @return boolean */ public function isExpected(Yay_Invocation $invocation) { $matches = true; $object = $invocation->getObject(); if ($object === $this->_object) { if (isset($this->_statePredicate)) { $matches = $this->_statePredicate->isActive(); } if ($matches && isset($this->_method)) { if ($this->_method == $invocation->getMethod()) { $args =& $invocation->getArguments(); foreach ($this->_matchers as $i => $m) { if (!array_key_exists($i, $args)) { if ($m->isOptional()) { break; } else { $matches = false; break; } } else { if (!$m->matches($args[$i])) { $matches = false; break; } } } } else { $matches = false; } } if ($matches && isset($this->_sequence)) { $matches = $this->_sequence->isInSequence($this->_wantedSequenceId); } } else { $matches = false; } if ($matches) { $this->notifyMatchedInvocation($invocation); } return $matches; } /** * Specify the Action to run if a match occurs. * @param Yay_Action $action */ public function will(Yay_Action $action) { $this->_action = $action; return $this; } /** * Only be expected when in the given State predicate. * @param Yay_StatePredicate $predicate */ public function when(Yay_StatePredicate $predicate) { $this->_statePredicate = $predicate; return $this; } /** * Activate the given $state if a match occurs. * @param Yay_State $state */ public function then(Yay_State $state) { $this->_state = $state; return $this; } /** * Constrain this expectation to be valid only if invoked in the given sequence. * @param Yay_Sequence $sequence */ public function inSequence(Yay_Sequence $sequence) { $this->_wantedSequenceId = $sequence->requestSequenceId(); $this->_sequence = $sequence; return $this; } /** * Get the Action for the given Invocation. * This may have been specified by a will() clause. * @param Yay_Invocation $invocation * @return Yay_Action */ public function getAction(Yay_Invocation $invocation) { if (isset($this->_state)) { $this->_state->activate(); } return $this->_action; } /** * Record any Invocations on the MockObject whilst it's in record mode. * @param Yay_Invocation $invocation */ public function recordInvocation(Yay_Invocation $invocation) { $this->_method = $invocation->getMethod(); $matchers =& $invocation->getArguments(); foreach ($matchers as $matcher) { if ($matcher instanceof Yay_Matcher) { $this->_matchers[] = $matcher; } else { $this->_matchers[] = new Yay_Matchers_IdenticalMatcher($matcher); } } } /** * Returns the Expectations. * @return array of Yay_Expectation */ public function getExpectations() { return array($this); } /** * Describe this Expectation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $this->describeBounds($description); $description->appendText(sprintf(' of %s;', $this->_getInvocationSignature())); if (isset($this->_sequence)) { $description->appendText(' in'); $this->_sequence->describeTo($description); } if (isset($this->_statePredicate)) { $description->appendText(' when'); $this->_statePredicate->describeTo($description); } if (isset($this->_action)) { $this->_action->describeTo($description); } $this->describeSatisfaction($description); } // -- Private methods private function _getInvocationSignature() { $class = Yay_MockGenerator::getInstance() ->reverseNamingScheme(get_class($this->_object)); if (isset($this->_method)) { $method = $this->_method; } else { $method = ''; } if (!empty($this->_matchers)) { $args = array(); foreach ($this->_matchers as $matcher) { $args[] = $matcher->describeMatch('%s [%s]'); } $params = implode(', ', $args); } else { $params = ''; } return sprintf('%s::%s(%s)', $class, $method, $params); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/AtLeastExpectation.php100644 0 0 4654 12000050366 25411 0ustar 0 0 . */ //require 'Yay/Expectations/AbstractExpectation.php'; //require 'Yay/Invocation.php'; /** * An Expectation which wants at least a set number of matching Invocations. * @author Chris Corbyn * @package Yay */ class Yay_Expectations_AtLeastExpectation extends Yay_Expectations_AbstractExpectation { /** * The expected Invocation count. * @var int * @access private */ private $_count = 0; /** * The number of matched Invocations. * @var int * @access private */ private $_matched = 0; /** * Create a new AtLeastExpectation expecting at least $n Invocations. * @param int $n */ public function __construct($n) { $this->_count = $n; } /** * Test if all conditions of the Invocation are satisfied. * @return boolean */ public function isSatisfied() { return ($this->_matched >= $this->_count); } /** * Increment the match counter by 1. * @param Yay_Invocation $invocation */ public function notifyMatchedInvocation(Yay_Invocation $invocation) { $this->_matched++; } /** * Describe the boundaries of how many invocations can occur. * @param Yay_Description $description */ public function describeBounds(Yay_Description $description) { if ($this->_count > 0) { $description->appendText(sprintf('At least %d', $this->_count)); } else { $description->appendText('Any number'); } } /** * Describe the current status of this expectation. * @param Yay_Description $description */ public function describeSatisfaction(Yay_Description $description) { if ($this->_matched >= $this->_count) { $description->appendText(' already'); } $description->appendText(sprintf(' occurred %d times', $this->_matched)); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/AtMostExpectation.php100644 0 0 5435 12000050366 25261 0ustar 0 0 . */ //require 'Yay/Expectations/AbstractExpectation.php'; //require 'Yay/Invocation.php'; /** * An Expectation which wants up to a set number of matching Invocations. * @author Chris Corbyn * @package Yay */ class Yay_Expectations_AtMostExpectation extends Yay_Expectations_AbstractExpectation { /** * The expected Invocation count. * @var int * @access private */ private $_count = 0; /** * The number of matched Invocations. * @var int * @access private */ private $_matched = 0; /** * Create a new AtMostExpectation expecting at most $n Invocations. * @param int $n */ public function __construct($n) { $this->_count = $n; } /** * Test if this Invocation is one that was expected by this Expectation. * @param Yay_Invocation $invocation * @return boolean */ public function isExpected(Yay_Invocation $invocation) { return parent::isExpected($invocation) && ($this->_matched <= $this->_count); } /** * Test if all conditions of the Invocation are satisfied. * @return boolean */ public function isSatisfied() { return true; } /** * Increment the match counter by 1. * @param Yay_Invocation $invocation */ public function notifyMatchedInvocation(Yay_Invocation $invocation) { $this->_matched++; } /** * Describe the boundaries of how many invocations can occur. * @param Yay_Description $description */ public function describeBounds(Yay_Description $description) { if ($this->_count > 0) { $description->appendText(sprintf('At most %d', $this->_count)); } else { $description->appendText('No invocations'); } } /** * Describe the current status of this expectation. * @param Yay_Description $description */ public function describeSatisfaction(Yay_Description $description) { if ($this->_matched >= $this->_count) { $description->appendText(' already'); } $description->appendText( sprintf( ' occurred %d times', (($this->_matched < $this->_count) ? $this->_matched : $this->_count) )); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/BetweenExpectation.php100644 0 0 5555 12000050366 25446 0ustar 0 0 . */ //require 'Yay/Expectations/AbstractExpectation.php'; //require 'Yay/Invocation.php'; /** * An Expectation which allows a boundary for a number of matching Invocations. * @author Chris Corbyn * @package Yay */ class Yay_Expectations_BetweenExpectation extends Yay_Expectations_AbstractExpectation { /** * The minimum Invocation count. * @var int * @access private */ private $_min = 0; /** * The maximum Invocation count. * @var int * @access private */ private $_max = 0; /** * The number of matched Invocations. * @var int * @access private */ private $_matched = 0; /** * Create a new BetweenExpectation expecting between $min and $max Invocations. * @param int $n */ public function __construct($min, $max) { $this->_min = $min; $this->_max = $max; } /** * Test if this Invocation is one that was expected by this Expectation. * @param Yay_Invocation $invocation * @return boolean */ public function isExpected(Yay_Invocation $invocation) { return parent::isExpected($invocation) && ($this->_matched <= $this->_max); } /** * Test if all conditions of the Invocation are satisfied. * @return boolean */ public function isSatisfied() { return ($this->_matched >= $this->_min); } /** * Increment the match counter by 1. * @param Yay_Invocation $invocation */ public function notifyMatchedInvocation(Yay_Invocation $invocation) { $this->_matched++; } /** * Describe the boundaries of how many invocations can occur. * @param Yay_Description $description */ public function describeBounds(Yay_Description $description) { $description->appendText(sprintf('Between %d and %d', $this->_min, $this->_max)); } /** * Describe the current status of this expectation. * @param Yay_Description $description */ public function describeSatisfaction(Yay_Description $description) { if ($this->_matched >= $this->_min) { $description->appendText(' already'); } $description->appendText( sprintf( ' occurred %d times', (($this->_matched < $this->_max) ? $this->_matched : $this->_max) )); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Expectations/ExactlyExpectation.php100644 0 0 5462 12000050366 25463 0ustar 0 0 . */ //require 'Yay/Expectations/AbstractExpectation.php'; //require 'Yay/Invocation.php'; /** * An Expectation which wants an exact number of matching Invocations. * @author Chris Corbyn * @package Yay */ class Yay_Expectations_ExactlyExpectation extends Yay_Expectations_AbstractExpectation { /** * The expected Invocation count. * @var int * @access private */ private $_count = 0; /** * The number of matched Invocations. * @var int * @access private */ private $_matched = 0; /** * Create a new ExactlyExpectation expecting $n Invocations. * @param int $n */ public function __construct($n) { $this->_count = $n; } /** * Test if this Invocation is one that was expected by this Expectation. * @param Yay_Invocation $invocation * @return boolean */ public function isExpected(Yay_Invocation $invocation) { return parent::isExpected($invocation) && ($this->_matched <= $this->_count); } /** * Test if all conditions of the Invocation are satisfied. * @return boolean */ public function isSatisfied() { return ($this->_matched >= $this->_count); } /** * Increment the match counter by 1. * @param Yay_Invocation $invocation */ public function notifyMatchedInvocation(Yay_Invocation $invocation) { $this->_matched++; } /** * Describe the boundaries of how many invocations can occur. * @param Yay_Description $description */ public function describeBounds(Yay_Description $description) { if ($this->_count > 0) { $description->appendText(sprintf('Exactly %d', $this->_count)); } else { $description->appendText('No invocations'); } } /** * Describe the current status of this expectation. * @param Yay_Description $description */ public function describeSatisfaction(Yay_Description $description) { if ($this->_matched >= $this->_count) { $description->appendText(' already'); } $description->appendText( sprintf( ' occurred %d times', (($this->_matched < $this->_count) ? $this->_matched : $this->_count) )); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Invocation.php100644 0 0 2452 12000050366 21305 0ustar 0 0 . */ //require 'Yay/SelfDescribing.php'; /** * A representation of a Method invocation. * This is a container for the object the method was invoked on, the method- * name and the arguments in the invocation. * @author Chris Corbyn * @package Yay */ interface Yay_Invocation extends Yay_SelfDescribing { /** * Get the object which this Invocation occured on. * @return object */ public function getObject(); /** * Get the method name of the invoked method. * @return string */ public function getMethod(); /** * Get the argument list in the Invocation. * @return array */ public function &getArguments(); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/InvocationHandler.php100644 0 0 2016 12000050366 22577 0ustar 0 0 . */ //require 'Yay/Invocation.php'; /** * Listens for Invocations and returns a suitable value. * @author Chris Corbyn * @package Yay */ interface Yay_InvocationHandler { /** * Handle the given $invocation and return a value for it. * @param Yay_Invocation $invocation * @return mixed */ public function &handleInvocation(Yay_Invocation $invocation); }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/InvocationProxy.php100644 0 0 4613 12000050366 22350 0ustar 0 0 . */ //require 'Yay/ExpectationProvider.php'; //require 'Yay/InvocationRecorder.php'; //require 'Yay/MockObject.php'; //require 'Yay/SimpleInvocation.php'; /** * Proxies Invocations on a Mock object to the recorder. * @author Chris Corbyn * @package Yay */ class Yay_InvocationProxy implements Yay_ExpectationProvider { /** * The InvocationRecorder which is using this InvocationProxy. * @var Yay_InvocationRecorder * @access private */ private $_recorder; /** * The Mock object where Invocations are recorded from. * @var Yay_MockObject * @access private */ private $_mock; /** * Create a new InvocationProxy for $recorder and $mock. * @param Yay_InvocationRecorder $recorder * @param Yay_MockObject $mock */ public function __construct(Yay_InvocationRecorder $recorder, Yay_MockObject $mock) { $this->_recorder = $recorder; $this->_mock = $mock; } /** * Direct all invocations to the recorder. * @param string $method * @param array $args * @return Yay_InvocationRecorder */ public function __call($method, $args) { if (is_callable(array($this->_mock, $method))) { $invocation = new Yay_SimpleInvocation($this->_mock, $method, $args); $this->_recorder->recordInvocation($invocation); return $this->_recorder; } elseif (is_callable(array($this->_recorder, $method))) { return call_user_func_array(array($this->_recorder, $method), $args); } else { throw new BadMethodCallException('Mock method ' . $method . ' does not exist'); } } /** * Returns the Expectation list. * @return array of Yay_Expectation */ public function getExpectations() { return $this->__call(__FUNCTION__, array()); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/InvocationRecorder.php100644 0 0 2065 12000050366 22773 0ustar 0 0 . */ //require 'Yay/Invocation.php'; //require 'Yay/ExpectationProvider.php'; /** * Listens for Invocations and provides expectations based on them. * @author Chris Corbyn * @package Yay */ interface Yay_InvocationRecorder extends Yay_ExpectationProvider { /** * Record the given $invocation. * @param Yay_Invocation $invocation */ public function recordInvocation(Yay_Invocation $invocation); }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matcher.php100644 0 0 2477 12000050366 20566 0ustar 0 0 . */ /** * The Matcher interface for comparing arguments. * @author Chris Corbyn * @package Yay */ interface Yay_Matcher { /** * Compare the $argument with whatever is expected to match it. * @param mixed $argument * @return boolean */ public function matches(&$argument); /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional(); /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/AnyMatcher.php100644 0 0 4051 12000050366 22772 0ustar 0 0 . */ //require 'Yay/Matcher.php'; /** * Allows anything to match. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_AnyMatcher implements Yay_Matcher { /** * A type to compare with. * @var string * @access private */ private $_type; /** * The desired result. * @var boolean * @access private */ private $_result; /** * Create a new AnyMatcher, optionally constrained only to objects of $type. * @param string $type, optional * @param boolean $result */ public function __construct($type = null, $result = true) { $this->_type = $type; $this->_result = $result; } /** * Always returns true where no type is given, and where the type matches otherwise. * @param mixed $value * @return boolean */ public function matches(&$value) { $return = (is_null($this->_type) || ($value instanceof $this->_type)); return (($this->_result && $return) || (!$this->_result && !$return)); } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return false; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { return 'ANYTHING'; } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/BoundsMatcher.php100644 0 0 4366 12000050366 23506 0ustar 0 0 . */ //require 'Yay/Matcher.php'; /** * Compares values to test if they are within given boundaries. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_BoundsMatcher implements Yay_Matcher { /** * The upper bound. * @var mixed * @access private */ private $_upper; /** * The lower bound. * @var mixed * @access private */ private $_lower; /** * The desired result. * @var boolean * @access private */ private $_result; /** * Create a new BoundsMatcher between $lower and $upper. * @param mixed $lower * @param mixed $upper * @param boolean $result which is wanted */ public function __construct($lower, $upper, $result = true) { $this->_upper = $upper; $this->_lower = $lower; $this->_result = $result; } /** * Compare $value with the boundaries and return true if it is within them. * @param mixed $value * @return boolean */ public function matches(&$value) { $return = ($value <= $this->_upper && $value >= $this->_lower); return (($this->_result && $return) || (!$this->_result && !$return)); } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return false; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { return sprintf($format, 'between', $this->_min . ' and ' . $this->_max); } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/EqualMatcher.php100644 0 0 2652 12000050366 23317 0ustar 0 0 . */ //require 'Yay/Matchers/IdenticalMatcher.php'; /** * Compares values for equality. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_EqualMatcher extends Yay_Matchers_IdenticalMatcher { /** * Create a new EqualMatcher expecting $expected. * @param mixed $expected * @param boolean $result to be expected */ public function __construct($expected, $result = true) { parent::__construct($expected, $result); } /** * Compare $value with the expected value and return true if it is equal. * @param mixed $value * @return boolean */ public function matches(&$value) { $return = (($this->_expected == $value) && ($value == $this->_expected)); return (($this->_result && $return) || (!$this->_result && !$return)); } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/IdenticalMatcher.php100644 0 0 5742 12000050366 24147 0ustar 0 0 . */ //require 'Yay/Matcher.php'; /** * Compares values for value and type. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_IdenticalMatcher implements Yay_Matcher { /** * The expected value. * @var mixed * @access protected */ protected $_expected; /** * The expected return value. * @var boolean * @access protected */ protected $_result; /** * Create a new IdenticalMatcher expecting $expected. * @param mixed $expected * @param boolean $result to be expected */ public function __construct($expected, $result = true) { $this->_expected = $expected; $this->_result = $result; } /** * Compare $value with the expected value and return true if it matches in * type and in value. * @param mixed $value * @return boolean */ public function matches(&$value) { $return = (($this->_expected === $value) && ($value === $this->_expected)); return (($this->_result && $return) || (!$this->_result && !$return)); } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return false; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { $description = ''; $value = $this->_expected; if (is_int($value)) { $description = sprintf($format, 'int', $value); } elseif (is_float($value)) { $description = sprintf($format, 'float', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_numeric($value)) { $description = sprintf($format, 'number', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_string($value)) { $description = sprintf($format, 'string', preg_replace('/^(.{8}).+/', '$1..', $value)); } elseif (is_object($value)) { $description = sprintf($format, 'object', get_class($value)); } elseif (is_array($value)) { $description = sprintf($format, 'array', count($value) . ' items'); } else { $description = sprintf($format, gettype($value), preg_replace('/^(.{8}).+/', '$1..', (string) $value)); } return $description; } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/OptionalMatcher.php100644 0 0 4473 12000050366 24040 0ustar 0 0 . */ //require 'Yay/Matcher.php'; //require 'Yay/Matchers/IdenticalMatcher.php'; /** * Wraps Matchers and makes them Optional. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_OptionalMatcher implements Yay_Matcher { /** * A matcher to delegate to. * @var Yay_Matcher * @access private */ private $_matcher; /** * Create a new OptionalMatcher, optionally wrapping $value. * @param mixed $value, optional */ public function __construct($value = null) { if (isset($value)) { if ($value instanceof Yay_Matcher) { $this->_matcher = $value; } else { $this->_matcher = new Yay_Matchers_IdenticalMatcher($value); } } } /** * Returns true if no matcher set, otherwise it delegates to the given Matcher. * @param mixed $value * @return boolean */ public function matches(&$value) { if (isset($this->_matcher)) { $matches = $this->_matcher->matches($value); } else { $matches = true; } return $matches; } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return true; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { $name = 'optional'; if (isset($this->_matcher)) { $value = $this->_matcher->describeMatch($format); } else { $value = '*'; } return sprintf($format, $name, $value); } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/PatternMatcher.php100644 0 0 4170 12000050366 23662 0ustar 0 0 . */ //require 'Yay/Matcher.php'; /** * Compares values against a PCRE pattern. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_PatternMatcher implements Yay_Matcher { /** * The expected pattern. * @var string * @access private */ private $_pattern; /** * The desired return value. * @var boolean * @access private */ private $_result; /** * Create a new PatternMatcher expecting $pattern. * @param string $pattern * @param boolean $result to be expected */ public function __construct($pattern, $result = true) { $this->_pattern = $pattern; $this->_result = $result; } /** * Compare $value with the expected pattern and return true if it matches. * @param string $value * @return boolean */ public function matches(&$value) { $return = ( (is_string($value) || is_numeric($value)) && preg_match($this->_pattern, $value) ); return (($this->_result && $return) || (!$this->_result && !$return)); } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return false; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { return sprintf($format, 'pattern', $this->_pattern); } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Matchers/ReferenceMatcher.php100644 0 0 4521 12000050366 24143 0ustar 0 0 . */ //require 'Yay/Matcher.php'; /** * Compares values to see if they reference one another. * @author Chris Corbyn * @package Yay */ class Yay_Matchers_ReferenceMatcher implements Yay_Matcher { /** * The expected reference. * @var mixed * @access private */ private $_ref; /** * The desired return value. * @var boolean * @access private */ private $_result; /** * Create a new IdenticalMatcher expecting $expected. * @param mixed $expected * @param boolean $result to be expected */ public function __construct(&$ref, $result = true) { $this->_ref =& $ref; $this->_result = $result; } /** * Compare $ref with the expected reference and return true if it is the same reference. * @param mixed $ref * @return boolean */ public function matches(&$ref) { if (is_object($ref)) { $isRef = ($this->_ref === $ref); } else { if ($this->_ref === $ref) { $copy = $ref; $randomString = uniqid('yay'); $ref = $randomString; $isRef = ($this->_ref === $ref); $ref = $copy; } else { $isRef = false; } } return (($this->_result && $isRef) || (!$this->_result && !$isRef)); } /** * Returns true if the argument doesn't need to be present. * @return boolean */ public function isOptional() { return false; } /** * Writes the match description as a string following $format. * $format is a sprintf() string with %s, $s as $matcherName, $value respectively. * @param string $format * @return string */ public function describeMatch($format) { return '[reference]'; } }Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/MockGenerator.php100644 0 0 17475 12000050366 21767 0ustar 0 0 . */ /** * Generates the code for a Mock object. * This lives as a singleton for a few reasons. * @author Chris Corbyn * @package Yay */ class Yay_MockGenerator { /** The name of the Mock object interface */ const MOCK_INTERFACE = 'Yay_MockObject'; /** Prefixed to types to create a Mock name */ const MOCK_PREFIX = 'Yay_MockObjects_'; /** Singleton instance */ private static $_instance = null; /** * The path a template which draws a Mock. * @var string * @access private */ private $_template; /** * A map of mocked type hints to their concrete class names. * @var array * @access private */ private $_mocked = array(); /** * Constructor cannot be used. */ private function __construct() { } /** * Get a singleton instance of this MockGenerator. * @return Yay_MockGenerator */ public static function getInstance() { if (is_null(self::$_instance)) { self::$_instance = new self(); } return self::$_instance; } /** * Set the path to a template which can draw a mock class. * @param string $path */ public function setMockTemplate($path) { $this->_template = $path; } /** * Produce class code for a MockObject of $typeHint and return its concrete name. * @param string $typeHint * @return string */ public function generateMock($typeHint) { if (!$className = $this->_getConcreteMockName($typeHint)) { $className = $this->_materializeMockCode($typeHint); } return $className; } /** * Use a fixed naming scheme to make a mock class name from $typeHint. * @param string $typeHint * @return string */ public function applyNamingScheme($typeHint) { return self::MOCK_PREFIX . $typeHint; } /** * Remove any adjustments that were made to an original type hint. * @param string $typeHint * @return string */ public function reverseNamingScheme($typeHint) { $len = strlen(self::MOCK_PREFIX); if (substr($typeHint, 0, $len) == self::MOCK_PREFIX) { $typeHint = substr($typeHint, $len); } return $typeHint; } // -- Private methods /** * Try to lookup a mocked concrete class name for $typeHint. * @param string $typeHint * @return string * @access private */ private function _getConcreteMockName($typeHint) { if (array_key_exists($typeHint, $this->_mocked)) { return $this->_mocked[$typeHint]; } } /** * Produce the mock object code and return its name. * @param string $typeHint * @return string * @access private */ private function _materializeMockCode($typeHint) { $reflector = new ReflectionClass($typeHint); $mockData = array( 'className' => $this->applyNamingScheme($typeHint), 'extends' => $this->_getSuperclass($reflector), 'interfaces' => $this->_getInterfaces($reflector), 'methods' => $this->_getMethods($reflector) ); extract($mockData); $code = include($this->_template); eval($code); $this->_mocked[$typeHint] = $mockData['className']; return $mockData['className']; } /** * Get all known interfaces for $reflector. * @param ReflectionClass $reflector * @return array * @access private */ private function _getInterfaces(ReflectionClass $reflector) { $interfaces = array(); if ($reflector->isInterface()) { if ($reflector->getName() != self::MOCK_INTERFACE) { $interfaces[] = $reflector->getName(); } } else { foreach ($reflector->getInterfaces() as $interfaceReflector) { if ($interfaceReflector->getName() != self::MOCK_INTERFACE) { $interfaces[] = $interfaceReflector->getName(); } } } return $interfaces; } /** * Get the superclass this mock object needs to extend. * @param ReflectionClass $reflector * @return string * @access private */ private function _getSuperclass(ReflectionClass $reflector) { if ($this->_canExtend($reflector)) { $superclass = $reflector->getName(); } else { $superclass = ''; } return $superclass; } /** * Get all methods from $reflector. * @param ReflectionClass $reflector * @return array * @access private */ private function _getMethods(ReflectionClass $reflector) { $methods = array(); foreach ($reflector->getMethods() as $reflectionMethod) { if ($reflectionMethod->isConstructor() || $reflectionMethod->getName() == '__clone') { continue; } if ($reflectionMethod->isPublic() || $reflectionMethod->isProtected()) { $methods[] = array( 'name' => $reflectionMethod->getName(), 'access' => $reflectionMethod->isPublic() ? 'public' : 'protected', 'modifiers' => $reflectionMethod->isStatic() ? 'static' : '', 'returnReference' => $reflectionMethod->returnsReference(), 'parameters' => $this->_getParameters($reflectionMethod) ); } } return $methods; } /** * Get all parameters for $method. * @param ReflectionMethod $method * @return array * @access private */ private function _getParameters(ReflectionMethod $method) { $parameters = array(); foreach ($method->getParameters() as $reflectionParameter) { $hint = ''; if ($reflectionParameter->isArray()) { $hint = 'array'; } elseif ($c = $reflectionParameter->getClass()) { $hint = $c->getName(); } $parameters[] = array( 'hint' => $hint, 'byReference' => $reflectionParameter->isPassedByReference(), 'optional' => $reflectionParameter->isOptional() ); } return $parameters; } /** * Determine if the reflector for the given class is safe to extend. * @param ReflectionClass $reflector * @return boolean * @access private */ private function _canExtend(ReflectionClass $reflector) { $canExtend = true; $warning = false; if ($reflector->isInterface()) { $canExtend = false; } else { if ($constructor = $reflector->getConstructor()) { if ($constructor->isPrivate() || $constructor->isFinal()) { $canExtend = false; $warning = 'has a private or final constructor'; } } elseif ($reflector->isFinal()) { $canExtend = false; $warning = 'is declared final'; } else { foreach ($reflector->getMethods() as $method) { if (($method->isPublic() || $method->isProtected()) && $method->isFinal()) { $canExtend = false; $warning = 'contains final methods'; } } } } if ($warning) { trigger_error( sprintf('The type [%s] to be mocked %s.' . ' Mocking classes which cannot be fully overridden results' . ' in a loss of class type. It is safe to supress this warning if you' . ' are aware of the conflict.', $reflector->getName(), $warning ), E_USER_WARNING ); } return $canExtend; } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/MockObject.php100644 0 0 1454 12000050366 21215 0ustar 0 0 . */ /** * A tag placed on any MockObjects generated in the context of YayMock. * @author Chris Corbyn * @package Yay */ interface Yay_MockObject { } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Mockery.php100644 0 0 11414 12000050366 20623 0ustar 0 0 . */ //require 'Yay/MockGenerator.php'; //require 'Yay/SimpleInvocation.php'; //require 'Yay/SimpleDescription.php'; //require 'Yay/InvocationHandler.php'; //require 'Yay/MockObject.php'; //require 'Yay/ExpectationProvider.php'; //require 'Yay/NotSatisfiedException.php'; //require 'Yay/StateMachine.php'; //require 'Yay/SimpleSequence.php'; /** * The main Yay context. * Handles the generation of MockObjects and the Invocation of methods. * @author Chris Corbyn * @package Yay */ class Yay_Mockery implements Yay_InvocationHandler { /** * The Expectation stack which is being checked. * @var array * @access private */ private $_expectations = array(); /** * Invocations which are not expected by any Expectations get caught here. * @var array * @access private */ private $_unexpectedInvocations = array(); /** * A mock class generator. * @var Yay_MockGenerator * @access private */ private $_generator; /** * Create a new Mockery. */ public function __construct() { $this->_generator = Yay_MockGenerator::getInstance(); } /** * Create a MockObject matching $typeHint. * If the $typeHint is an interface the Mock will implement the interface * and maintain the method signatures from that interface. * If the $typeHint is a class name the Mock will extend the class overriding * all public methods (HOWEVER, if the class contains final methods it is not * possible to override all methods and hence, the mock will have no specific * type. * @param string $typeHint * @return Yay_MockObject */ public function mock($typeHint) { $className = $this->_generator->generateMock($typeHint); $reflector = new ReflectionClass($className); return $reflector->newInstance($this); } /** * Specify an Expectation (or Expectations) to check. * @param Yay_ExpectationProvider $provider */ public function checking(Yay_ExpectationProvider $provider) { foreach ($provider->getExpectations() as $expectation) { $this->_expectations[] = $expectation; } } /** * Get a state machine named $name. * @param string $name * @return Yay_States */ public function states($name) { return new Yay_StateMachine($name); } /** * Create a new Sequence named $name. * @param string $name * @return Yay_Sequence */ public function sequence($name) { return new Yay_SimpleSequence($name); } /** * Used by YayMock internally (ignore this method!). */ public function &handleInvocation(Yay_Invocation $invocation) { $ret = null; $expected = false; foreach ($this->_expectations as $expectation) { if ($expectation->isExpected($invocation)) { $expected = true; if ($action = $expectation->getAction($invocation)) { $ret =& $action->invoke($invocation); } break; } } if (!$expected) { $this->_unexpectedInvocations[] = $invocation; } return $ret; } /** * Assert that all Expectations are satisfied. * Throws an Exception of type Yay_NotSatisfiedException if any Expecations * are not satisfied. * @throws Yay_NotSatisfiedException */ public function assertIsSatisfied() { $description = new Yay_SimpleDescription(); $satisfied = true; foreach ($this->_unexpectedInvocations as $invocation) { $description->appendText('Unexpected invocation'); $invocation->describeTo($description); $description->appendText(PHP_EOL); $satisfied = false; } if (!$satisfied) { $description->appendText(PHP_EOL); } foreach ($this->_expectations as $expectation) { if (!$expectation->isSatisfied()) { $description->appendText('* '); $satisfied = false; } $expectation->describeTo($description); $description->appendText(PHP_EOL); } if (!$satisfied) { throw new Yay_NotSatisfiedException( 'Not all expectations were satisfied or a method was invoked unexpectedly.' . PHP_EOL . PHP_EOL . $description->toString() . PHP_EOL ); } } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/NotSatisfiedException.php100644 0 0 2001 12000050366 23435 0ustar 0 0 . */ /** * The Exception thrown by Context::assertIsSatisfied() if assertion fails. * @author Chris Corbyn * @package Yay */ class Yay_NotSatisfiedException extends Exception { /** * Create a new NotSatisfiedException with $message. * @param string $message */ public function __construct($message) { parent::__construct($message); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SelfDescribing.php100644 0 0 2036 12000050366 22055 0ustar 0 0 . */ //require 'Yay/Description.php'; /** * Components implementing this can describe what they do to a Description instance. * @author Chris Corbyn * @package Yay */ interface Yay_SelfDescribing { /** * Write a description of this self describing object to Description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/Sequence.php100644 0 0 2375 12000050366 20750 0ustar 0 0 . */ //require 'Yay/SelfDescribing.php'; /** * Provides a means for Expectations to verify they are called in the correct order. * This allows Invocations to be forced in a particular order. * @author Chris Corbyn * @package Yay */ interface Yay_Sequence extends Yay_SelfDescribing { /** * Ask for a new Sequence Id and register the new sequence. * @return int $id */ public function requestSequenceId(); /** * Check if the sequence has progressed far enough for this sequence ID to be used. * @param int $id * @return boolean */ public function isInSequence($sequenceId); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SimpleDescription.php100644 0 0 2726 12000050366 22635 0ustar 0 0 . */ //require 'Yay/Description.php'; /** * A basic Description container for error messages. * @author Chris Corbyn * @package Yay */ class Yay_SimpleDescription implements Yay_Description { /** * An internal text buffer. * @var string * @access private */ private $_text = ''; /** * Append an existing Description to this Description. * @param Yay_Description */ public function appendDescription(Yay_Description $description) { $this->_text .= $description->toString(); } /** * Append text content to this Description. * @param string $text */ public function appendText($text) { $this->_text .= $text; } /** * Get this description back as a formatted string. * @return string */ public function toString() { return $this->_text; } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SimpleInvocation.php100644 0 0 7565 12000050366 22471 0ustar 0 0 . */ //require 'Yay/Invocation.php'; //require 'Yay/MockGenerator.php'; /** * The standard implementation of the Invocation interface. * @author Chris Corbyn * @package Yay */ class Yay_SimpleInvocation implements Yay_Invocation { /** * The Object on which the Inovation occurred. * @var object * @access private */ private $_object; /** * The method name invoked. * @var string * @access private */ private $_method; /** * The arguments in the Invocation. * @var array * @access private */ private $_arguments; /** * Create a new SimpleInvocation with the given details. * @param object $object * @param string $method * @param array &$arguments */ public function __construct($object, $method, array &$arguments) { $this->_object = $object; //Massage __call() overloading so the interface is tested correctly if ($method == '__call') { $method = array_shift($arguments); $args =& array_shift($arguments); $arguments =& $args; } $this->_method = $method; $this->_arguments =& $arguments; } /** * Get the object which this Invocation occured on. * @return object */ public function getObject() { return $this->_object; } /** * Get the method name of the invoked method. * @return string */ public function getMethod() { return $this->_method; } /** * Get the argument list in the Invocation. * @return array */ public function &getArguments() { return $this->_arguments; } /** * Describe this Invocation to $description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(sprintf(' of %s;', $this->_getInvocationSignature())); } // -- Private methods private function _getInvocationSignature() { $class = Yay_MockGenerator::getInstance() ->reverseNamingScheme(get_class($this->_object)); if (!empty($this->_arguments)) { $args = array(); foreach ($this->_arguments as $arg) { $args[] = $this->_describeArgument($arg, '%s [%s]'); } $params = implode(', ', $args); } else { $params = ''; } return sprintf('%s::%s(%s)', $class, $this->_method, $params); } private function _describeArgument($arg, $format) { $description = ''; if (is_int($arg)) { $description = sprintf($format, 'int', $arg); } elseif (is_float($arg)) { $description = sprintf($format, 'float', preg_replace('/^(.{8}).+/', '$1..', $arg)); } elseif (is_numeric($arg)) { $description = sprintf($format, 'number', preg_replace('/^(.{8}).+/', '$1..', $arg)); } elseif (is_string($arg)) { $description = sprintf($format, 'string', preg_replace('/^(.{8}).+/', '$1..', $arg)); } elseif (is_object($arg)) { $description = sprintf($format, 'object', get_class($arg)); } elseif (is_array($arg)) { $description = sprintf($format, 'array', count($arg) . ' items'); } else { $description = sprintf($format, gettype($arg), preg_replace('/^(.{8}).+/', '$1..', (string) $arg)); } return $description; } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SimpleSequence.php100644 0 0 4726 12000050366 22124 0ustar 0 0 . */ /** * Provides a means for Expectations to verify they are called in the correct order. * This allows Invocations to be forced in a particular order. * @author Chris Corbyn * @package Yay */ class Yay_SimpleSequence implements Yay_Sequence { /** * The name of this sequence. * @var string * @access private */ private $_name; /** * The list of sequence IDs expected. * @var array * @access private */ private $_sequenceIds = array(); /** * An internal sequence counter. * @var int * @access private */ private $_counter = 0; /** * The current position in the sequence. * @var int * @access private */ private $_currentId = null; /** * Create a new Sequence with $name. * @param string $name */ public function __construct($name) { $this->_name = $name; } /** * Ask for a new Sequence Id and register the new sequence. * @return int $id */ public function requestSequenceId() { $id = $this->_counter++; $this->_sequenceIds[] = $id; return $id; } /** * Check if the sequence has progressed far enough for this sequence ID to be used. * @param int $id * @return boolean */ public function isInSequence($sequenceId) { if ($this->_currentId === $sequenceId) { $inSequence = true; } elseif (current($this->_sequenceIds) === $sequenceId) { $this->_currentId = array_shift($this->_sequenceIds); $inSequence = true; } else { $inSequence = false; } return $inSequence; } /** * Write a description of this self describing object to Description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(sprintf(' sequence %s;', $this->_name)); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SimpleState.php100644 0 0 2467 12000050366 21434 0ustar 0 0 . */ //require 'Yay/State.php'; //require 'Yay/States.php'; //require 'Yay/SimpleStatePredicate.php'; /** * A State from a State machine. * @author Chris Corbyn * @package Yay */ class Yay_SimpleState extends Yay_SimpleStatePredicate implements Yay_State { /** * Create a new State for $stateMachine to be $stateName. * @param Yay_States $stateMachine * @param string $stateName */ public function __construct(Yay_States $stateMachine, $stateName) { parent::__construct($stateMachine, $stateName, true); } /** * Make this State active. */ public function activate() { $this->_stateMachine->become($this->_stateName); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/SimpleStatePredicate.php100644 0 0 4437 12000050366 23254 0ustar 0 0 . */ //require 'Yay/StatePredicate.php'; //require 'Yay/States.php'; /** * An expectation about what State a state machine is in. * @author Chris Corbyn * @package Yay */ class Yay_SimpleStatePredicate implements Yay_StatePredicate { /** * The state machine which this predicate checks. * @var Yay_States * @access private */ protected $_stateMachine; /** * The state name to check for in the state machine. * @var string * @access private */ protected $_stateName; /** * True if the state is wanted, false otherwise. * @var boolean * @access private */ private $_is = true; /** * Create a new StatePredicate. * @param Yay_States $stateMachine * @param string $stateName to expect * @param boolean $is (negation point) */ public function __construct(Yay_States $stateMachine, $stateName, $is = true) { $this->_stateMachine = $stateMachine; $this->_stateName = $stateName; $this->_is = $is; } /** * Return true if the state machine is in this state. * @return boolean */ public function isActive() { return (($this->_is && $this->_stateMachine->getCurrentState() == $this->_stateName) || (!$this->_is && $this->_stateMachine->getCurrentState() != $this->_stateName)); } /** * Write a description of this self describing object to Description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $this->_stateMachine->describeTo($description); $description->appendText(sprintf( ' %s %s;', ($this->_is ? 'is' : 'is not'), $this->_stateName )); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/State.php100644 0 0 1615 12000050366 20254 0ustar 0 0 . */ //require 'Yay/StatePredicate.php'; /** * A State from a State machine. * @author Chris Corbyn * @package Yay */ interface Yay_State extends Yay_StatePredicate { /** * Make this State active. */ public function activate(); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/StateMachine.php100644 0 0 4773 12000050366 21551 0ustar 0 0 . */ //require 'Yay/State.php'; //require 'Yay/SimpleState.php'; //require 'Yay/StatePredicate.php'; //require 'Yay/SimpleStatePredicate.php'; /** * A basic state machine. * @author Chris Corbyn * @package Yay */ class Yay_StateMachine implements Yay_States { /** * The name of this state machine. * @var string * @access private */ private $_name; /** * The current state. * @var string * @access private */ private $_state; /** * Create a new State machine with $name. * @param string $name */ public function __construct($name) { $this->_name = $name; } /** * Set the initial state of this state machine. * @param string $stateName * @return Yay_States */ public function startsAs($stateName) { $this->become($stateName); return $this; } /** * Get the state which puts the state machine into the named state. * @param string $stateName * @return Yay_State */ public function is($stateName) { return new Yay_SimpleState($this, $stateName); } /** * Get the predicate which indicates the state machine is NOT in the named state. * @param string $stateName * @return Yay_StatePredicate */ public function isNot($stateName) { return new Yay_SimpleStatePredicate($this, $stateName, false); } /** * Become the named state. * @param string $stateName */ public function become($stateName) { $this->_state = $stateName; } /** * Get the name of the current state. * @return string */ public function getCurrentState() { return $this->_state; } /** * Write a description of this self describing object to Description. * @param Yay_Description $description */ public function describeTo(Yay_Description $description) { $description->appendText(sprintf(' %s', $this->_name)); } } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/StatePredicate.php100644 0 0 1737 12000050366 22102 0ustar 0 0 . */ //require 'Yay/SelfDescribing.php'; /** * An expectation about what State a state machine is in. * @author Chris Corbyn * @package Yay */ interface Yay_StatePredicate extends Yay_SelfDescribing { /** * Return true if the state machine is in this state. * @return boolean */ public function isActive(); } Swift-4.2.1/test-suite/lib/yaymock/classes/Yay/States.php100644 0 0 3056 12000050366 20440 0ustar 0 0 . */ //require 'Yay/SelfDescribing.php'; /** * A basic state machine. * @author Chris Corbyn * @package Yay */ interface Yay_States extends Yay_SelfDescribing { /** * Set the initial state of this state machine. * @param string $stateName * @return Yay_States */ public function startsAs($stateName); /** * Get the state which puts the state machine into the named state. * @param string $stateName * @return Yay_State */ public function is($stateName); /** * Get the predicate which indicates the state machine is NOT in the named state. * @param string $stateName * @return Yay_StatePredicate */ public function isNot($stateName); /** * Become the named state. * @param string $stateName */ public function become($stateName); /** * Get the name of the current state. * @return string */ public function getCurrentState(); } Swift-4.2.1/test-suite/lib/yaymock/mock.tpl.php100644 0 0 3730 12000050366 16524 0ustar 0 0 . */ ?> class implements Yay_MockObject { private $_yayInvocationHandler; public function __construct(Yay_InvocationHandler $invocationHandler) { $this->_yayInvocationHandler = $invocationHandler; } function ( $param): ?> 0) echo ','; ?> $arg_ ) { $value = null; if (isset($this->_yayInvocationHandler)) { $args = array(); for ($i = 0; $i < func_num_args(); ++$i) { $argName = 'arg_' . $i; $args[] =& ${$argName}; } $invocation = new Yay_SimpleInvocation($this, __FUNCTION__, $args); $value =& $this->_yayInvocationHandler->handleInvocation($invocation); } return $value; } public function __clone() { $this->_yayInvocationHandler = null; } } Swift-4.2.1/test-suite/lib/yaymock/yay_convenience.php100644 0 0 6357 12000050366 20163 0ustar 0 0 . */ /** * Provides non-namespaced classes and functions for brevity. * Including this script is entirely optional. * @author Chris Corbyn * @package Yay */ // Classes /** * Allow occurences of Yay_Expectations::create() to be replaced with Expectations::create(). */ class Expectations extends Yay_Expectations { } /** * Allows occurences of new Yay_Mockery() to be replaced with new Mockery(). */ class Mockery extends Yay_Mockery { } //Argument matchers /** * Allows Yay::optional() to be called as optional(). */ function optional($value = null) { return Yay::optional($value); } /** * Allows Yay::any() to be called as any(). */ function any($type = null) { return Yay::any($type); } /** * Allows Yay::none() to be called as none(). */ function none($type = null) { return Yay::none($type); } /** * Allows Yay::identical() to be called as identical(). */ function identical($value) { return Yay::identical($value); } /** * Allows Yay::notIdentical() to be called as notIdentical(). */ function notIdentical($value) { return Yay::notIdentical($value); } /** * Allows Yay::equal() to be called as equal(). */ function equal($value) { return Yay::equal($value); } /** * Allows Yay::notEqual() to be called as notEqual(). */ function notEqual($value) { return Yay::notEqual($value); } /** * Allows Yay::pattern() to be called as pattern(). */ function pattern($pattern) { return Yay::pattern($pattern); } /** * Allows Yay::noPattern() to be called as noPattern(). */ function noPattern($pattern) { return Yay::noPattern($pattern); } /** * Allows Yay::bounds() to be called as bounds(). */ function bounds($a, $b) { return Yay::bounds($a, $b); } /** * Allows Yay::outside() to be called as outside(). */ function outside($a, $b) { return Yay::outside($a, $b); } /** * Allows Yay::reference() to be called as reference(). */ function reference(&$ref) { return Yay::reference($ref); } /** * Allows Yay::noReference() to be called as noReference(). */ function noReference(&$ref) { return Yay::noReference($ref); } //Actions /** * Allows Yay::returnValue() to be called as returnValue(). */ function returnValue($value) { return Yay::returnValue($value); } /** * Allows Yay::returnReference() to be called as returnReference(). */ function returnReference(&$ref) { return Yay::returnReference($ref); } /** * Allows Yay::throwException() to be called as throwException(). */ function throwException(Exception $e) { return Yay::throwException($e); } /** * Allows Yay::call() to be called as call(). */ function call($callback) { return Yay::call($callback); } Swift-4.2.1/test-suite/lib/yaymock/yay_mock.php100644 0 0 1700 12000050366 16603 0ustar 0 0 . */ /** * YayMock include and bootstrap file. * @author Chris Corbyn */ require_once dirname(__FILE__) . '/classes/Yay.php'; Yay::setClassPath(dirname(__FILE__) . '/classes'); spl_autoload_register(array('Yay', 'autoload')); Yay_MockGenerator::getInstance()->setMockTemplate(dirname(__FILE__) . '/mock.tpl.php'); //EOF Swift-4.2.1/test-suite/run.php100644 0 0 2544 12000050366 13361 0ustar 0 0 get('//./root/cimv2:Win32_Process.Handle="' . getmypid() . '"') ->executablePath; } } $runner = new Sweety_Runner_CliRunner( explode(PATH_SEPARATOR, SWEETY_TEST_PATH), $exe . ' ' . $argv[0] ); $name = !empty($argv[1]) ? $argv[1] : 'All Tests'; $runner->setReporter(new Sweety_Reporter_CliReporter(sprintf('%s - %s', SWEETY_SUITE_NAME, $name))); $runner->setIgnoredClassRegex(SWEETY_IGNORED_CLASSES); $locators = preg_split('/\s*,\s*/', SWEETY_TEST_LOCATOR); foreach ($locators as $locator) { $runner->registerTestLocator(new $locator()); } if (!empty($argv[1]) && !preg_match('~!?/.*?/~', $argv[1])) { $testName = $argv[1]; $format = !empty($argv[2]) ? $argv[2] : Sweety_Runner::REPORT_TEXT; $runner->runTestCase($testName, $format); } else { $runner->runAllTests(); } Swift-4.2.1/test-suite/sweety.js100644 0 0 27261 12000050366 13745 0ustar 0 0 /* JavaScript wrapper around REST API in Sweety. */ /** * A convenience class for using XPath. * @author Chris Corbyn * @constructor */ function SweetyXpath() { /** * Get the first node matching the given expression. * @param {String} expr * @param {Element} node * @returns Element */ this.getFirstNode = function getFirstNode(expr, node) { var firstNode = _getRootNode(node).evaluate( expr, node, _getNsResolver(node), XPathResult.FIRST_ORDERED_NODE_TYPE, null); return firstNode.singleNodeValue; }, /** * Get all nodes matching the given expression. * The returned result is a Node Snapshot. * @param {String} expr * @param {Element} node * @returns Element[] */ this.getNodes = function getNodes(expr, node) { var nodes = _getRootNode(node).evaluate( expr, node, _getNsResolver(node), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var nodeSet = new Array(); for (var i = 0, len = nodes.snapshotLength; i < len; i++) { nodeSet.push(nodes.snapshotItem(i)); } return nodeSet; }, /** * Get the string value of the node matching the given expression. * @param {String} expr * @param {Element} node * @returns String */ this.getValue = function getValue(expr, node) { return _getRootNode(node).evaluate( expr, node, _getNsResolver(node), XPathResult.STRING_TYPE, null).stringValue; } /** * Get the root node from which run evaluate. * @param {Element} node * @returns Element */ var _getRootNode = function _getRootNode(node) { if (node.ownerDocument && node.ownerDocument.evaluate) { return node.ownerDocument; } else { if (node.evaluate) { return node; } else { return document; } } } /** * Get the NS Resolver used when searching. * @param {Element} node * @returns Element */ var _getNsResolver = function _getNsResolver(node) { if (!document.createNSResolver) { return null; } if (node.ownerDocument) { return document.createNSResolver(node.ownerDocument.documentElement); } else { return document.createNSResolver(node.documentElement); } } } /** * The reporter interface so Sweety can tell the UI what's happening. * @author Chris Corbyn * @constructor */ function SweetyReporter() { //Interface/Base Class var _this = this; /** * Create a sub-reporter for an individual test case. * @param {String} testCaseName * @returns SweetyReporter */ this.getReporterFor = function getReporterFor(testCaseName) { return _this; } /** * Start reporting. */ this.start = function start() { } /** * Handle a skipped test case. * @param {String} message * @param {String} path */ this.reportSkip = function reportSkip(message, path) { } /** * Handle a passing assertion. * @param {String} message * @param {String} path */ this.reportPass = function reportPass(message, path) { } /** * Handle a failing assertion. * @param {String} message * @param {String} path */ this.reportFail = function reportFail(message, path) { } /** * Handle an unexpected exception. * @param {String} message * @param {String} path */ this.reportException = function reportException(message, path) { } /** * Handle miscellaneous test output. * @param {String} output * @param {String} path */ this.reportOutput = function reportOutput(output, path) { } /** * Finish reporting. */ this.finish = function finish() { } } /** * Represents a single test case being run. * @author Chris Corbyn * @constructor */ function SweetyTestCaseRun(testClass, reporter) { var _this = this; /** The XMLHttpRequest used in testing */ var _req; /** XPath handler */ var _xpath = new SweetyXpath(); /** Callback function for completion event */ this.oncompletion = function oncompletion() { } /** * Run this test. */ this.run = function run() { if (!reporter.isStarted()) { reporter.start(); } _req = _createHttpRequest(); if (!_req) { return; } _req.open("GET", "?test=" + testClass + "&format=xml", true); _req.onreadystatechange = _handleXml; _req.send(null); } /** * Get an XmlHttpRequest instance, cross browser compatible. * @return Object */ var _createHttpRequest = function _createHttpRequest() { var req = false; if (window.XMLHttpRequest && !(window.ActiveXObject)) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if (window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } return req; } /** * Handle the XML response from the test. */ var _handleXml = function _handleXml() { if (_req.readyState == 4) { try { var xml = _req.responseXML; var txt = _req.responseText.replace(/[\r\n]+/g, ""). replace(/^(.+)<\?xml.*$/, "$1"); //Test case was skipped var skipElements = xml.getElementsByTagName('skip'); if (!skipElements || 1 != skipElements.length) { var runElements = xml.getElementsByTagName('run'); //Invalid document, an error probably occured if (!runElements || 1 != runElements.length) { reporter.reportException( "Invalid XML response: " + _stripTags(txt.replace(/^\s*<\?xml.+<\/(?:name|pass|fail|exception)>/g, "")), testClass); } else { var everything = runElements.item(0); _parseResults(everything, testClass); reporter.finish(); } } else { reporter.reportSkip(_textValueOf(skipElements.item(0)), testClass); reporter.finish(); } } catch (ex) { //Invalid document or an error occurred. reporter.reportException( "Invalid XML response: " + _stripTags(txt.replace(/^\s*<\?xml.+<\/(?:name|pass|fail|exception)>/g, "")), testClass); } //Invoke the callback _this.oncompletion(); } } /** * Cross browser method for reading the value of a node in XML. * @param {Element} node * @returns String */ var _textValueOf = function _textValueOf(node) { if (!node.textContent && node.text) { return node.text; } else { return node.textContent; } } var _stripTags = function _stripTags(txt) { txt = txt.replace(/[\r\n]+/g, ""); return txt.replace( /<\/?(?:a|b|br|p|strong|u|i|em|span|div|ul|ol|li|table|thead|tbody|th|td|tr)\b.*?\/?>/g, ""); } /** * Parse an arbitrary message output. * @param {Element} node * @param {String} path */ var _parseMessage = function _parseMessage(node, path) { reporter.reportOutput(_textValueOf(node), path); } /** * Parse formatted text output (such as a dump()). * @param {Element} node * @param {String} path */ var _parseFormatted = function _parseFormatted(node, path) { reporter.reportOutput(_textValueOf(node), path); } /** * Parse failing test assertion. * @param {Element} node * @param {String} path */ var _parseFail = function _parseFail(node, path) { reporter.reportFail(_textValueOf(node), path); } /** * Parse an Exception. * @param {Element} node * @param {String} path */ var _parseException = function _parseException(node, path) { reporter.reportException(_textValueOf(node), path); } /** * Parse passing test assertion. * @param {Element} node * @param {String} path */ var _parsePass = function _parsePass(node, path) { reporter.reportPass(_textValueOf(node), path); } /** * Parse an entire test case * @param {Element} node * @param {String} path */ var _parseTestCase = function _parseTestCase(node, path) { var testMethodNodes = _xpath.getNodes("./test", node); for (var x in testMethodNodes) { var testMethodNode = testMethodNodes[x]; var testMethodName = _xpath.getValue("./name", testMethodNode); var formattedNodes = _xpath.getNodes("./formatted", testMethodNode); for (var i in formattedNodes) { var formattedNode = formattedNodes[i]; _parseFormatted(formattedNode, path + " -> " + testMethodName); } var messageNodes = _xpath.getNodes("./message", testMethodNode); for (var i in messageNodes) { var messageNode = messageNodes[i]; _parseMessage(messageNode, path + " -> " + testMethodName); } var failNodes = _xpath.getNodes("./fail", testMethodNode); for (var i in failNodes) { var failNode = failNodes[i]; _parseFail(failNode, path + " -> " + testMethodName); } var exceptionNodes = _xpath.getNodes("./exception", testMethodNode); for (var i in exceptionNodes) { var exceptionNode = exceptionNodes[i]; _parseException(exceptionNode, path + " -> " + testMethodName); } var passNodes = _xpath.getNodes("./pass", testMethodNode); for (var i in passNodes) { var passNode = passNodes[i]; _parsePass(passNode, path + " -> " + testMethodName); } } } /** * Parse an entire grouped or single test case. * @param {Element} node * @param {String} path */ var _parseResults = function _parseResults(node, path) { var groupNodes = _xpath.getNodes("./group", node); if (0 != groupNodes.length) { for (var i in groupNodes) { var groupNode = groupNodes[i]; var groupName = _xpath.getValue("./name", groupNode); _parseResults(groupNode, path + " -> " + groupName); } } else { var caseNodes = _xpath.getNodes("./case", node); for (var i in caseNodes) { var caseNode = caseNodes[i]; _parseTestCase(caseNode, path); } } } } /** * Runs a list of test cases. * @author Chris Corbyn * @constructor */ function SweetyTestRunner() { var _this = this; SweetyTestRunner._currentInstance = _this; /** True if the test runner has been stopped */ var _cancelled = false; /** * Invoked to cause the test runner to stop execution at the next available * opportunity. If XML is being parsed in another thread, or an AJAX request * is in progress the test runner will wait until the next test. * @param {Boolean} cancel */ this.cancelTesting = function cancelTesting(cancel) { _cancelled = cancel; } /** * Run the given list of test cases. * @param {String[]} tests * @param {SweetyReporter} reporter */ this.runTests = function runTests(tests, reporter) { if (!reporter.isStarted()) { reporter.start(); } if (_cancelled || !tests || !tests.length) { _cancelled = false; reporter.finish(); return; } var testCase = tests.shift(); var caseReporter = reporter.getReporterFor(testCase); var testRun = new SweetyTestCaseRun(testCase, caseReporter); //Repeat until no tests remaining in list // Ok, I know, I know I'll try to eradicate this lazy use of recursion testRun.oncompletion = function() { _this.runTests(tests, reporter); }; testRun.run(); } } /** Active instance */ SweetyTestRunner._currentInstance = null; /** * Fetches the currently running instance of the TestRunner. * @returns SweetyTestRunner */ SweetyTestRunner.getCurrentInstance = function getCurrentInstance() { return this._currentInstance; } Swift-4.2.1/test-suite/templates/sweety/css/main.css100644 0 0 5403 12000050366 17605 0ustar 0 0 /** Page structure **/ /*------------------*/ ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input { margin: 0; padding: 0; } body { font-size: 0.8em; font-family: arial,sans-serif; background: #fff; padding: 8px; } img { border: 0; } input { margin-bottom: 8px; padding: 4px; font-size: 16px; width: 100px; } input.sweety-text { border: 2px solid #000; width: 268px; background-color: #fff; } input.sweety-disabled { background: #eee; border: 2px solid #888; } input.sweety-waiting { background-image: url(../images/loading.gif); background-position: 98% 50%; background-repeat: no-repeat; } input.sweety-check { width: 12px !important; height: 12px !important; margin: 1px !important; padding: 1px !important; } h1 { margin-bottom: 1em; } div#sweety-page { width: 100%; } div#sweety-testlist { float: left; width: 400px; background: #aaa; } div#sweety-output { margin-left: 400px; } div#sweety-results { padding: 8px; font-size: 1.4em; } div#sweety-messages { margin-top: 8px; padding-top: 8px; border-top: 1px solid #777; } div#sweety-smoke-images { margin-top: 8px; padding-top: 8px; } div#sweety-smoke-images img { width: 150px; height: 120px; margin-right: 8px; } div.sweety-clear { width: 100%; clear: both; } /** Look and feel **/ /*-----------------*/ input#sweety-filter { visibility: hidden; } div#sweety-communication { float: right; display: none; } pre.sweety-raw-output { display: block; background: #ddd; padding: 4px; margin: 4px; } div.sweety-pad { padding: 8px; } div.sweety-message { padding: 4px; margin: 4px; } div.sweety-test-path { padding-left: 2em; font-style: italic; color: #777; } div.sweety-test { font-size: 12px; margin-bottom: 2px; margin-left: 12px; padding: 2px; } div.sweety-test img { float: right; margin-right: 4px; } div.sweety-package-header { font-size: 12px; margin-bottom: 2px; border-bottom: 2px solid #444; padding: 2px; } div.sweety-package-header span.sweety-test-package { font-weight: normal; } div.sweety-package-header img { margin: 0 2px; } span.sweety-pkg-count { display: block; float: right; padding-right: 2px; } img.sweety-group-icon { float: right; margin: 4px !important; } .sweety-pkg-idle { background: #cacaca; } span.sweety-test-package { display: block; font-size: 10px; padding-left: 1em; } .sweety-idle { background: #eee; } .sweety-running { background: #ffff33 !important; } .sweety-pass { background: #00aa00 !important; color: #fff; } .sweety-fail { background: #ee0000 !important; color: #fff; } .sweety-fail-text { color: #ee0000; } .sweety-skip-text { color: #4444dd; font-weight: bold; text-decoration: underline; } Swift-4.2.1/test-suite/templates/sweety/images/darr.gif100644 0 0 71 12000050366 20177 0ustar 0 0 GIF89a €ÿÿÿÿÿÿ!ù, „™¡¯\’*Þ¼ó;Swift-4.2.1/test-suite/templates/sweety/images/group.gif100644 0 0 132 12000050366 20421 0ustar 0 0 GIF89a ‘>"ü÷õÿÿÿ!ù, +” ©y}¢nÙ.”qwŽ-™2†Þ‚È’—¥Óêª&\’3N g§é ;Swift-4.2.1/test-suite/templates/sweety/images/htmlicon.gif100644 0 0 1776 12000050366 21141 0ustar 0 0 GIF89a÷ÿÿÿøøø¢ñæïöè5“ãx¶ê¥éÿ­öÇÿ¦ó‘é7ÍÿÀÿ¼ý ƒá©Óñ›îyÞfW…ã¦ÎïŒçZl£Ëçäï÷ î±ø‹æ¦Ï𚦙í¦î¹üK+`rxÉóÃÿÆü €Cj ³ÉÅÿ¿ÿ²ùcVN8x¹ì/¼÷xRÇÿ¶ú/®šyw'¡fbD>'ŒÀÀþ@ÐÿA»©” ‘N»”lÙùWÕÿ-¹ÉyCOB v— Çÿ8Îÿ=¸š•S¿vãçzÞãÿoÛÿ(¢| ‰äXD z™KÑþJÐö›¥±wÔyÈñÿßÿRÑór\H&”¾áü:¹ °'Ã/̳éÏ©êÿ€ßÿOÍço_KuÁëêõø– Ÿ´'È*͕⾅ÜÕl×íFÌí¶Ì` hNæñ÷‡Ð¥š«¹$½ EÂX¡ ’/ÃÞÃÿ¥Ó¥ØïÔ«5µ[iÕÕ¨ Ÿ ’–>Æÿ¿ý¦Ý÷ìõø¤æüNŸ.¶š ¯š3³¡{Úûæóø*¥?*¥?)¤>)£=(£=(¢<(¢<'¡;'¡;' :& :&Ÿ9%ž8%ž8%7$7$œ6$œ6#›5#›5"š4"™3"™3!˜2!˜2!—1 —1 –0–0•/”.”.“-“-’,’,‘+‘+*))Ž(Ž(''Œ&Œ&‹%Š$Š$‰#‰#ˆ"ˆ"‡!‡!† ……„„ƒƒ‚€€~~}||{{ z z y y x w w v v u u t ts r r q q p p o !ù,ÛH°`AK0eÒ´‰“ƒ5rô(P$I“(U*( :„ =:„(‘¢EåÌ TÇÎP` Á@˜C‡ >8€@Ë h4€1áˆh$€ hR Ê‹\\°àb@!ù , 1(p€Á*Lh`áÀ ,x`ဆ È áŠ; äD…!ù , 3 ° @ Xh°à€‡ 4 qà‚`À€Š ;r²áF‡& –!ù , 6<  Á‚<È@†@Œ8€Ä‚*:4(Ñ€4¼è± H‹K 0‘eÁ€!ù , 0 8  A <`¡Ã‡#2`°bA $` À€ `ü² I‡!ù ,8<À@ Á 0á!L0’<µ‚ H,¢ÃHCQ|•]0‚(ˆè²T~e‰ÀcÀ(HH@Wfq2ÕU$A^3d0Ⱥ­õWæd•H"Áv¡ð°NQä4À v r_&¸˜&0!ùw, €ww!ùw, €ww!ùw, €ww‚ w!ùw, €!ùw, €w …!ùw,  € wƒ„w!ùw, #€w$w ww…wŽ‘" Žw›™™Ž•w!ùw,   €w1w…†‡ˆw!ùw, €wwww!ùw,€w‚‡w‹‡‚ w!ùw, €w‚wƒƒˆˆ  ƒˆ – Œ˜!ùw,€" wwwˆw‰‚‚!ùw, € !ùw, 5€w‚‚‚w ‚†Œ‚w‹Œ•†˜‚ ˜ ™w  §§›ˆ‚¤wž ˜›‚!ùw, €w ƒ!ùw,! € …$!ùw,#€!ùw, 3€‚ƒ„ƒw  wwŽ‘‚w–‘‚ŽŒ Ž‚w–w ‰ŒŽw…°‚!ùw,"€!ùw, € wˆ ˆˆˆ‘!ùw, €ww1ˆ wŒˆ‚w!ùw,! €wƒ„w!ùw, €‚…w…wŽŽwŽŠw‚„†!ùw,"€ !ùw, €‚ƒƒ ww‰wЉww$„ƒ!ùw,!€„…ww„‡w†Їw!ùw,"€ !ùw,"€ww w!ùw," €www!ùw,#€!ùw,"€w;Swift-4.2.1/test-suite/templates/sweety/images/rarr.gif100644 0 0 73 12000050366 20217 0ustar 0 0 GIF89a €ÿÿÿÿÿÿ!ù, ‚‰vºÜ4jÒ7eÖ·vï$;Swift-4.2.1/test-suite/templates/sweety/images/runicon.gif100644 0 0 237 12000050366 20750 0ustar 0 0 GIF89a¢ÿÿÿÌÌÌ™™™fff333ÿÿÿ!ù,dhºÜþ€H2ž5@èQ¸ Á0‚˜¦DA|ÐØt!´¯ÅÝ5-d§GË4(`@àJ˜ŠÉÕìhRëškl WÛ'€ƒ18&ÍìT2/8¯Y-ø€UÈËZìûBP€ƒ} ;Swift-4.2.1/test-suite/templates/sweety/images/xmlicon.gif100644 0 0 200 12000050366 20732 0ustar 0 0 GIF89a ¢ÿȤ?ÿÿÿÿ‚/ÿfÿÿÿ!ù, EXºÜþ0.@«½˜0ºÿ`8lb)’à©j:´ê¶ˆ¡ëÂÞÿ„ÞN—óyFá°xD*5%sH­.Ö¬5Àíz¿`o;Swift-4.2.1/test-suite/templates/sweety/js/sweety-template.js100644 0 0 72214 12000050366 21506 0ustar 0 0 /* JavaScript for Sweety to wrap the standard template around the API. */ /** * The UI Manager object for setting up the interface. * @author Chris Corbyn * @constructor */ function SweetyUIManager() { var _this = this; /** Packages toggled on or off */ var _pkgs = { }; /** Test cases within packages */ var _pkgTests = { }; /** An element cache */ var _cached = { }; /** * Initialize the user interface. */ this.initialize = function initialize() { _this.showFilterBox(); _this.loadTestList(); _this.resetMessageDiv(); _this.resetTotals(); } /** * Show or hide an entire package. * @param {String} pkg * @param {Boolean} onoff */ this.togglePackage = function togglePackage(pkg, onOff) { if (typeof _pkgs[pkg] == "undefined") { _pkgs[pkg] = true; } //Toggle if not overridden _pkgs[pkg] = (typeof onOff == "undefined") ? !_pkgs[pkg] : onOff; var pkgState = _pkgs[pkg] ? "1" : "0"; var date = new Date(); date.setTime(date.getTime() + (30 * 24 * 60 * 60 * 1000)); document.cookie = escape("sweetyPkg" + pkg) + "=" + pkgState + "; expires=" + date.toGMTString() + "; path=/"; var pkgRegex = new RegExp("^" + pkg + "_[^_]+$"); for (var testCase in sweetyTestCases) { if (testCase.match(pkgRegex)) { var testDiv = _getElementById(testCase); if (_pkgs[pkg]) { if (sweetyTestCases[testCase]) { testDiv.style.display = "block"; } } else { testDiv.style.display = "none"; } } } var headerImg; if (headerImg = _getElementById("sweety-pkg-img-" + pkg)) { if (_pkgs[pkg]) { headerImg.src = "templates/sweety/images/darr.gif"; } else { headerImg.src = "templates/sweety/images/rarr.gif"; } } } /** * Enable or disable user input. * @param {Boolean} on */ this.allowInteractivity = function allowInteractivity(on) { if (!on) { _paintFilterDisabled(true); _getRunButton().value = "Stop Tests"; _getRunButton().onclick = function() { try { SweetyTestRunner.getCurrentInstance().cancelTesting(true); _this.allowInteractivity(true); } catch (e) { } }; for (var testCase in sweetyTestCases) { _getElementById(testCase).onclick = function() { return false; }; } } else { _paintFilterDisabled(false); _getRunButton().value = "Run Tests"; _getRunButton().onclick = function() { _this.initialize(); sweetyRunner.runAll(); }; for (var testCase in sweetyTestCases) { _getElementById(testCase).onclick = function() { _this.initialize(); sweetyRunner.runTestCase(this.id); }; } } } /** * Display the filter box. */ this.showFilterBox = function showFilterBox() { _getFilter().style.visibility = 'visible'; } /** * Restore the UI on a new page load or reload. */ this.restore = function restore() { for (var testName in sweetyTestCases) { var pkgName = _pkgFor(testName); if (typeof _pkgTests[pkgName] == "undefined") { _pkgTests[pkgName] = { }; } _pkgTests[pkgName][testName] = true; } this.hideCheckboxes(); _loadPkgsFromCookie(); for (var pkg in _pkgs) { this.togglePackage(pkg, _pkgs[pkg]); } } /** * Hide all the checkboxes which are only applicable to the non-JS version. */ this.hideCheckboxes = function hideCheckboxes() { var inputs = document.getElementsByTagName("input"); for (var i = 0, len = inputs.length; i < len; i++) { if (inputs.item(i).className == "sweety-check") { inputs.item(i).style.display = "none"; } } delete inputs; } /** * Load the available test case list in the UI. */ this.loadTestList = function loadTestList() { var caseBox = _getListContainer(); //Show or hide any tests for (var testCase in sweetyTestCases) { var pkgName = _pkgFor(testCase); _pkgTests[pkgName][testCase] = sweetyTestCases[testCase]; this.paintTestCaseIdle(testCase); var pkg = _pkgFor(testCase); this.paintPkgIdle(pkg); var testDiv = _getElementById(testCase); //Make it look idle testDiv.className = "sweety-test sweety-idle"; if (sweetyTestCases[testCase]) { if (typeof _pkgs[pkg] == "undefined") { testDiv.style.display = "block"; } else if (_pkgs[pkg]) { testDiv.style.display = "block"; } } else { testDiv.style.display = "none"; } } //Show or hide any packages for (var pkgName in _pkgTests) { var display = false; var len = 0; for (var testCase in _pkgTests[pkgName]) { if (_pkgTests[pkgName][testCase]) { display = true; //break; len++; } } this.showPkgCount(pkgName, len); this.showHidePkg(pkgName, display); } } /** * Shows or hides the headers for the given package. * @param {String} pkg * @param {Boolean} show */ this.showHidePkg = function showHidePkg(pkg, show) { var pkgDiv = _getElementById("sweety-package-" + pkg); if (show) { pkgDiv.style.display = "block"; } else { pkgDiv.style.display = "none"; } } this.showPkgCount = function showPkgCount(pkg, n) { var countBox = _getElementById("sweety-pkg-count-" + pkg); _setContent(countBox, "(" + n + ")"); } /** * Reset all the aggregate results in the UI. */ this.resetTotals = function resetTotals() { _this.paintNumCases(0); _this.paintNumRun(0); _this.paintNumPasses(0); _this.paintNumFails(0); _this.paintNumExceptions(0); _this.paintAllIdle(); } /** * Paint or unpaint the networking icon to indicate communication with the server. * @param {Boolean} on */ this.paintNetworking = function paintNetworking(on) { if (on) { _getCommIcon().style.display = "block"; } else { _getCommIcon().style.display = "none"; } } /** * Flush the contents of the assertion message area. */ this.resetMessageDiv = function resetMessageDiv() { _getMessages().innerHTML = ""; _getElementById("sweety-smoke-images").innerHTML = ""; } /** * Marks a given package as running (yellow) in the UI. * @param {String} pkg */ this.paintPkgRunning = function paintPkgRunning(pkg) { _getElementById("sweety-package-" + pkg).className = "sweety-package-header sweety-running"; } /** * Marks a given package as idle (grey) in the UI. * @param {String} pkg */ this.paintPkgIdle = function paintPkgIdle(pkg) { _getElementById("sweety-package-" + pkg).className = "sweety-package-header sweety-pkg-idle"; } /** * Marks a given package as passed (green) in the UI. * @param {String} pkg */ this.paintPkgPassed = function paintPkgPassed(pkg) { _getElementById("sweety-package-" + pkg).className = "sweety-package-header sweety-pass"; } /** * Marks a given package as failed (red) in the UI. * @param {String} pkg */ this.paintPkgFailed = function paintPkgFailed(pkg) { _getElementById("sweety-package-" + pkg).className = "sweety-package-header sweety-fail"; } /** * Marks a given test case as running (yellow) in the UI. * @param {String} testCase */ this.paintTestCaseRunning = function paintTestCaseRunning(testCase) { _getElementById(testCase).className = "sweety-test sweety-running"; } /** * Marks a given test case as idle (grey) in the UI. * @param {String} testCase */ this.paintTestCaseIdle = function paintTestCaseIdle(testCase) { _getElementById(testCase).className = "sweety-test sweety-idle"; } /** * Marks a given test case as failed (red) in the UI. * @param {String} testCase */ this.paintTestCaseFailed = function paintTestCaseFailed(testCase) { _getElementById(testCase).className = "sweety-test sweety-fail"; } /** * Marks a given test case as passed (green) in the UI. * @param {String} testCase */ this.paintTestCasePassed = function paintTestCasePassed(testCase) { _getElementById(testCase).className = "sweety-test sweety-pass"; } /** * Paints a skipped testcase message to the message area. * @param {String} message * @param {String} path */ this.paintSkip = function paintSkip(message, path) { var skipDiv = document.createElement("div"); skipDiv.className = "sweety-message"; var skipLabel = _createSkipLabel("Skip"); skipDiv.appendChild(skipLabel); var messageSpan = document.createElement("strong"); _setContent(messageSpan, ": " + message); skipDiv.appendChild(messageSpan); var pathDiv = _createPathDiv(path); skipDiv.appendChild(pathDiv); _getMessages().appendChild(skipDiv); } /** * Paints an unexpected exception notice to the message area. * @param {String} message * @param {String} path */ this.paintException = function paintException(message, path) { var exceptionDiv = document.createElement("div"); exceptionDiv.className = "sweety-message"; var exceptionLabel = _createFailLabel("Exception"); exceptionDiv.appendChild(exceptionLabel); var messageSpan = document.createElement("strong"); _setContent(messageSpan, ": " + message); exceptionDiv.appendChild(messageSpan); var pathDiv = _createPathDiv(path); exceptionDiv.appendChild(pathDiv); _getMessages().appendChild(exceptionDiv); } /** * Paints a failed assertion message to the message area. * @param {String} message * @param {String} path */ this.paintFail = function paintFail(message, path) { var failDiv = document.createElement("div"); failDiv.className = "sweety-message"; var failLabel = _createFailLabel("Fail"); failDiv.appendChild(failLabel); var messageSpan = document.createElement("span"); _setContent(messageSpan, ": " + message); failDiv.appendChild(messageSpan); var pathDiv = _createPathDiv(path); failDiv.appendChild(pathDiv); _getMessages().appendChild(failDiv); } /** * Paints dump() output to the message area. * @param {String} output * @param {String} path */ this.paintOutput = function paintOutput(output, path) { var refs; if (refs = /^\{image @ (.*?)\}$/.exec(output)) { this.paintSmokeImage(refs[1]); } else { var outputPane = document.createElement("pre"); outputPane.className = "sweety-raw-output"; _setContent(outputPane, output); _getMessages().appendChild(outputPane); } } this.paintSmokeImage = function paintSmokeImage(imageSrc) { var imagePane = _getElementById("sweety-smoke-images"); var smokeImg = document.createElement("img"); smokeImg.title = 'Smoke test image'; smokeImg.src = imageSrc; smokeImg.style.cursor = 'pointer'; smokeImg.onclick = function() { window.open(imageSrc); }; imagePane.appendChild(smokeImg); } /** * Paints an internal message to the message area. * @param {String} message * @param {String} path */ this.paintMessage = function paintMessage(message) { var messageDiv = document.createElement("div"); messageDiv.className = "sweety-message sweety-running"; _setContent(messageDiv, message); _getMessages().appendChild(messageDiv); } /** * Paints the current number of test cases to the summary bar. * @param {Number} num */ this.paintNumCases = function paintNumCases(num) { _setContent(_getCases(), num); } /** * Paints the current number of finished test cases to the summary bar. * @param {Number} num */ this.paintNumRun = function paintNumRun(num) { _setContent(_getComplete(), num); } /** * Paints the current number of passing assertions to the summary bar. * @param {Number} num */ this.paintNumPasses = function paintNumPasses(num) { _setContent(_getPasses(), num); } /** * Paints the current number of failing assertions to the summary bar. * @param {Number} num */ this.paintNumFails = function paintNumFails(num) { _setContent(_getFails(), num); } /** * Paints the current number of exceptions to the summary bar. * @param {Number} num */ this.paintNumExceptions = function paintNumExceptions(num) { _setContent(_getExceptions(), num); } /** * Paints the summary bar (green) as passed. */ this.paintConclusionPassed = function paintConclusionPassed() { _getResultsBar().className = "sweety-pass"; } /** * Paints the summary bar (red) as failed. */ this.paintConclusionFailed = function paintConclusionFailed() { _getResultsBar().className = "sweety-fail"; } /** * Paints the summary bar (yellow) as running. */ this.paintAllRunning = function paintAllRunning() { _getResultsBar().className = "sweety-running"; } /** * Paints the summary bar (grey) as idle. */ this.paintAllIdle = function paintAllIdle() { _getResultsBar().className = "sweety-idle"; } /** * Puts the filter box in searching L&F. */ this.paintSearching = function paintSearching() { _getFilter().className = "sweety-text sweety-waiting"; } /** * Returns the filter box the idle L&F. */ this.paintSearchComplete = function paintSearchComplete() { _getFilter().className = "sweety-text"; } /** * Apply data to a page element. * @param {Element} el * @param {String} content */ var _setContent = function _setContent(el, content) { if (typeof el.textContent != "undefined") { el.textContent = content; } else { el.innerHTML = content; } } /** * Create a label used at the start of a message to indicate a skipped test case. * @param {String} label * @returns HTMLSpanElement */ var _createSkipLabel = function _createSkipLabel(label) { var skipLabel = document.createElement("span"); skipLabel.className = "sweety-skip-text"; _setContent(skipLabel, label); return skipLabel; } /** * Create a label used at the start of a message to indicate failure. * @param {String} label * @returns HTMLSpanElement */ var _createFailLabel = function _createFailLabel(label) { var failLabel = document.createElement("span"); failLabel.className = "sweety-fail-text"; _setContent(failLabel, label); return failLabel; } /** * Creates the text which shows the complete pathway to a test method. * The path includes all groups, the test case and the test method. * @param {String} path * @returns HTMLDivElement */ var _createPathDiv = function _createPathDiv(path) { var pathDiv = document.createElement("div"); pathDiv.className = "sweety-test-path"; _setContent(pathDiv, "in " + path); return pathDiv; } var _paintFilterDisabled = function _paintFilterDisabled(disabled) { if (disabled) { _getFilter().disabled = true; _getFilter().className = "sweety-text sweety-disabled"; } else { _getFilter().disabled = false; _getFilter().className = "sweety-text"; } } /** * A caching wrapper around document.getElementById(). * @param {String} id * @returns Element */ var _getElementById = function _getElementById(elId) { if (!_cached[elId]) { _cached[elId] = document.getElementById(elId); } return _cached[elId]; } /** * Get the icon which shows network activity. * @returns Element */ var _getCommIcon = function _getCommIcon() { return _getElementById("sweety-communication"); } /** * Get the container which holds the list of test cases. * @returns Element */ var _getListContainer = function _getListContainer() { return _getElementById("sweety-testlist-container"); } /** * Get the container where all assertion messages go. * @returns Element */ var _getMessages = function _getMessages() { return _getElementById("sweety-messages"); } /** * Get the element for number of test cases. * @returns Element */ var _getCases = function _getCases() { return _getElementById("sweety-num-cases"); } /** * Get the container for number of test cases finished. * @returns Element */ var _getComplete = function _getComplete() { return _getElementById("sweety-num-run"); } /** * Get the container for number of exceptions. * @returns Element */ var _getExceptions = function _getExceptions() { return _getElementById("sweety-num-exceptions"); } /** * Get the container for number of fails. * @returns Element */ var _getFails = function _getFails() { return _getElementById("sweety-num-fails"); } /** * Get the container for number of passes. * @returns Element */ var _getPasses = function _getPasses() { return _getElementById("sweety-num-passes"); } /** * Get the bar showing aggregate results. * @returns Element */ var _getResultsBar = function _getResutsBar() { return _getElementById("sweety-results"); } /** * Get the filter input box. * @returns Element */ var _getFilter = function _getFilter() { return _getElementById("sweety-filter"); } /** * Get the button which operates the filter. * @returns Element */ var _getRunButton = function _getRunButton() { return _getElementById("sweety-run-button"); } var _loadPkgsFromCookie = function _loadPkgsFromCookie() { for (var testCase in sweetyTestCases) { var pkg = _pkgFor(testCase); _pkgs[pkg] = false; } var cookieBits = document.cookie.split(/\s*;\s*/g); for (var i in cookieBits) { if (cookieBits[i].substring(0, 9) != "sweetyPkg") { continue; } var nvp = cookieBits[i].substring(9).split('='); _pkgs[unescape(nvp[0])] = (nvp[1] == "0") ? false : true; //alert(unescape(nvp[0]) + " => " + _pkgs[unescape(nvp[0])]); } } var _pkgFor = function _pkgFor(testName) { return testName.replace(/_?[^_]+$/, ""); } } //Create an instance of the UI Manager for usage var sweetyUI = new SweetyUIManager(); /** * A filter to hide/show test cases in the list. * @author Chris Corbyn * @consructor */ function SweetyFilter() { var _this = this; /** Asynchronous page timer (so nothing happens whilst typing) */ var _timer; /** The sweety-filter element, lazy loaded */ var _filter = null; /** * Update the display once the search is complete. */ this.repaintUI = function repaintUI() { sweetyUI.initialize(); sweetyUI.paintSearchComplete(); } /** * Search for matching test cases. */ this.search = function search() { sweetyUI.paintSearching(); var query = _getFilterInput().value.toLowerCase(); var queryBits = query.split(/[^\!a-zA-Z0-9_]+/g); //Cancel searching if still typing try { window.clearTimeout(_timer); } catch (e) { } for (var testCase in sweetyTestCases) { for (var i in queryBits) { var testFor = queryBits[i]; var isNegated = ("!" == testFor.charAt(0)); if (isNegated) { testFor = testFor.substring(1); } if (!isNegated && 0 > testCase.toLowerCase().indexOf(testFor)) { sweetyTestCases[testCase] = false; break; } else if (isNegated && 0 < testCase.toLowerCase().indexOf(testFor)) { sweetyTestCases[testCase] = false; break; } else { sweetyTestCases[testCase] = true; } } } //Only apply the search in 500ms, since user may be typing _timer = window.setTimeout(_this.repaintUI, 500); } /** * Get a lazy loaded reference to the input element. * @return HTMLInputElement */ var _getFilterInput = function _getFilterInput() { if (!_filter) { _filter = document.getElementById("sweety-filter"); } return _filter; } } //Create a new instance of the filter var sweetyFilter = new SweetyFilter(); /** * The reporter which gathers aggregate results and displays a summary. * @author Chris Corbyn * @constructor * @param {Boolean} reportPkgs if package status should be reported */ function SweetyTemplateAggregateReporter(testCaseList, reportPkgs) { var _this = this; /** True if this reporter instance is running now */ var _started = false; /** Aggregate totals */ var _aggregates = { cases : 0, run: 0, passes : 0, fails : 0, exceptions : 0 }; /** Aggregates per-package */ var _pkgs = { }; /** Currently running package */ var _currentPkg; /** * Creates a reporter for the given testCase. * @param {String} testCase * @returns SweetyReporter */ this.getReporterFor = function getReporterFor(testCase) { _aggregates.cases++; if (reportPkgs) { var pkg = _getPkgName(testCase); sweetyUI.paintPkgRunning(pkg); _pkgs[pkg].cases++; if (_currentPkg && _currentPkg != pkg) { _updatePkgStatus(_currentPkg); } _currentPkg = pkg; } sweetyUI.paintNumCases(_aggregates.cases); var reporter = new SweetyTemplateCaseReporter(testCase, _this); return reporter; } /** * Updates the UI with the new aggregate totals. */ this.notifyEnded = function notifyEnded(testCase) { _aggregates.run++; if (reportPkgs) { var pkg = _getPkgName(testCase); _pkgs[pkg].run++; } //Update the UI with new totals sweetyUI.paintNumRun(_aggregates.run); sweetyUI.paintNumPasses(_aggregates.passes); sweetyUI.paintNumFails(_aggregates.fails); sweetyUI.paintNumExceptions(_aggregates.exceptions); } /** * Returns true if this reporter instance is running. * @returns Boolean */ this.isStarted = function isStarted() { return _started; } /** * Start reporting. */ this.start = function start() { _started = true; if (reportPkgs) { for (var i = 0, len = testCaseList.length; i < len; i++) { var testCase = testCaseList[i]; var pkg = _getPkgName(testCase); if (typeof _pkgs[pkg] == "undefined") { _pkgs[pkg] = { cases : 0, run : 0, passes : 0, fails : 0, exceptions : 0 }; } } } sweetyUI.allowInteractivity(false); sweetyUI.paintNetworking(true); sweetyUI.paintAllRunning(); } /** * Report a skipped test case. * @param {String} message * @param {String} path */ this.reportSkip = function reportSkip(message, path) { sweetyUI.paintSkip(message, path); } /** * Report a passing assertion. * @param {String} message * @param {String} path */ this.reportPass = function reportPass(message, path) { _aggregates.passes++; if (reportPkgs) { _pkgs[_currentPkg].passes++; } } /** * Report a failing assertion. * @param {String} message * @param {String} path */ this.reportFail = function reportFail(message, path) { _aggregates.fails++; if (reportPkgs) { _pkgs[_currentPkg].fails++; } sweetyUI.paintFail(message, path); } /** * Report an unexpected exception. * @param {String} message * @param {String} path */ this.reportException = function reportException(message, path) { _aggregates.exceptions++; if (reportPkgs) { _pkgs[_currentPkg].exceptions++; } sweetyUI.paintException(message, path); } /** * Handle test case output from something like a dump(). * @param {String} output * @param {String} path */ this.reportOutput = function reportOutput(output, path) { sweetyUI.paintOutput(output, path); } /** * End reporting. * This method is used to come to a conclusion about the test results in the UI. */ this.finish = function finish() { _started = false; if (reportPkgs) { _updatePkgStatus(_currentPkg); } sweetyUI.allowInteractivity(true); sweetyUI.paintNetworking(false); if ((!_aggregates.fails && !_aggregates.exceptions) && (_aggregates.cases == _aggregates.run)) { sweetyUI.paintConclusionPassed(); } else { sweetyUI.paintConclusionFailed(); } var incompleteCount = _aggregates.cases - _aggregates.run; //Check if all tests actually got fully parsed (i.e. finished) if (0 < incompleteCount) { sweetyUI.paintMessage( incompleteCount + " test case(s) did not complete." + " This may be because invalid XML was output during the test run" + " and/or because an error occured." + " Incomplete test cases are shown in yellow. Click the HTML link " + "next to the test for more detail."); } } var _getPkgName = function _getPkgName(testCase) { return testCase.replace(/_?[^_]+$/, ""); } var _updatePkgStatus = function _updatePkgStatus(pkg) { if ((!_pkgs[pkg].fails && !_pkgs[pkg].exceptions) && (_pkgs[pkg].cases == _pkgs[pkg].run)) { sweetyUI.paintPkgPassed(pkg); } else if (_pkgs[pkg].cases == _pkgs[pkg].run) { sweetyUI.paintPkgFailed(pkg); } } } SweetyTemplateAggregateReporter.prototype = new SweetyReporter(); /** * The reporter class per-test case. * @author Chris Corbyn * @consructor */ function SweetyTemplateCaseReporter(testCase, reporter) { var _this = this; /** Aggregate totals */ var _aggregates = { passes : 0, fails : 0, exceptions : 0 }; /** The DIV element showing this test case */ var _testCaseDiv = document.getElementById(testCase); /** True only if this reporter is running */ var _started = false; /** * Stubbed only to return itself. * @returns SweetyReporter */ this.getReporterFor = function getReporterFor(testCase) { return _this; } /** * Returns true when the reporter is started. * @returns Boolean */ this.isStarted = function isStarted() { return _started; } /** * Start reporting. */ this.start = function start() { _started = true; sweetyUI.paintTestCaseRunning(testCase); } /** * Report a skipped test case. * @param {String} message * @param {String} path */ this.reportSkip = function reportSkip(message, path) { reporter.reportSkip(message, path); } /** * Report a passing assertion. * @param {String} message * @param {String} path */ this.reportPass = function reportPass(message, path) { _aggregates.passes++; reporter.reportPass(message, path); } /** * Report a failing assertion. * @param {String} message * @param {String} path */ this.reportFail = function reportFail(message, path) { _aggregates.fails++; reporter.reportFail(message, path); } /** * Report an unexpected exception. * @param {String} message * @param {String} path */ this.reportException = function reportException(message, path) { _aggregates.exceptions++; reporter.reportException(message, path); } /** * Handle output from a test case in the form of something like a dump(). * @param {String} output * @param {string} path */ this.reportOutput = function reportOutput(output, path) { reporter.reportOutput(output, path); } /** * End reporting. */ this.finish = function finish() { _started = false; if (!_aggregates.fails && !_aggregates.exceptions) { sweetyUI.paintTestCasePassed(testCase); } else { sweetyUI.paintTestCaseFailed(testCase); } reporter.notifyEnded(testCase); } } SweetyTemplateCaseReporter.prototype = new SweetyReporter(); /** * Wraps the invokation of SweetyTestRunner. * @author Chris Corbyn * @constructor */ function SweetyTestWrapper() { var _this = this; /** * Run a single test case. * @param {String} testClass */ this.runTestCase = function runTestCase(testClass) { var testCaseList = new Array(); testCaseList.push(testClass); var reporter = new SweetyTemplateAggregateReporter(testCaseList); var runner = new SweetyTestRunner(); runner.runTests(testCaseList, reporter); } /** * Run all selected test cases. */ this.runAll = function runAll(pkg) { var pkgRegex; if (pkg) { pkgRegex = new RegExp("^" + pkg + "_[^_]+$"); } var testCaseList = new Array(); for (var testCase in sweetyTestCases) { if (!sweetyTestCases[testCase] || (pkg && !testCase.match(pkgRegex))) { continue; } testCaseList.push(testCase); } var reporter = new SweetyTemplateAggregateReporter(testCaseList, true); var runner = new SweetyTestRunner(); runner.runTests(testCaseList, reporter); } } //Create an instance of the test runner for usage var sweetyRunner = new SweetyTestWrapper(); if (typeof document.onreadystatechange != "undefined") { //IE 6/7 document.onreadystatechange = function() { if (document.readyState == "complete") { sweetyUI.restore(); sweetyUI.initialize(); } }; } else { //Fallback window.onload = function() { sweetyUI.restore(); sweetyUI.initialize(); }; try { //FF document.addEventListener("DOMContentLoaded", window.onload, false); } catch (e) { } } Swift-4.2.1/test-suite/templates/sweety/suite-ui-noajax.tpl.php100644 0 0 13633 12000050366 21734 0ustar 0 0 <?php echo $suiteName; ?> - No AJAX
Not available Tests
As XML As HTML Run checked="checked" />

- No AJAX

/ test cases complete: passes, fails and exceptions.
Skip:
in
Fail:
in
Exception:
in
Swift-4.2.1/test-suite/templates/sweety/suite-ui.tpl.php100644 0 0 13030 12000050366 20445 0ustar 0 0 <?php echo $suiteName; ?>
Toggle Display Tests
As XML As HTML Run checked="checked" />
Communicating

0/0 test cases complete: 0 passes, 0 fails and 0 exceptions.
Swift-4.2.1/test-suite/xpath-legacy.js100644 0 0 225333 12000050366 15033 0ustar 0 0 /* JavaScript-XPath 0.1.5 * (c) 2007 Cybozu Labs, Inc. * * JavaScript-XPath is freely distributable under the terms of an MIT-style license. * For details, see the JavaScript-XPath web site: http://coderepos.org/share/wiki/JavaScript-XPath * /*--------------------------------------------------------------------------*/ if (!document.implementation || !document.implementation.hasFeature || !document.implementation.hasFeature("XPath", null)) (function() { var undefined = void(0); var defaultConfig = { targetFrame: undefined }; var config; if (window.jsxpath) { config = window.jsxpath; } else { var scriptElms = document.getElementsByTagName('script'); var scriptElm = scriptElms[scriptElms.length - 1]; var scriptSrc = scriptElm.src; config = {}; var scriptSrcMatchResult = scriptSrc.match(/\?(.*)$/); if (scriptSrcMatchResult) { var configStrings = scriptSrcMatchResult[1].split('&'); for (var i = 0, l = configStrings.length; i < l; i ++) { var configString = configStrings[i]; var configStringSplited = configString.split('='); config[configStringSplited[0]] = configStringSplited[1] || true; } } } for (var n in defaultConfig) { if (!(n in config)) config[n] = defaultConfig[n] } var BinaryExpr; var FilterExpr; var FunctionCall; var Literal; var NameTest; var NodeSet; var NodeType; var NodeUtil; var Number; var PathExpr; var Step; var UnaryExpr; var UnionExpr; var VariableReference; /* * object: user agent identifier */ var uai = new function() { var ua = navigator.userAgent; if (RegExp == undefined) { if (ua.indexOf("Opera") >= 0) { this.opera = true; } else if (ua.indexOf("Netscape") >= 0) { this.netscape = true; } else if (ua.indexOf("Mozilla/") == 0) { this.mozilla = true; } else { this.unknown = slide } if (ua.indexOf("Gecko/") >= 0) { this.gecko = true; } if (ua.indexOf("Win") >= 0) { this.windows = true; } else if (ua.indexOf("Mac") >= 0) { this.mac = true; } else if (ua.indexOf("Linux") >= 0) { this.linux = true; } else if (ua.indexOf("BSD") >= 0) { this.bsd = true; } else if (ua.indexOf("SunOS") >= 0) { this.sunos = true; } } else { /* for Trident/Tasman */ /*@cc_on @if (@_jscript) function jscriptVersion() { switch (@_jscript_version) { case 3.0: return "4.0"; case 5.0: return "5.0"; case 5.1: return "5.01"; case 5.5: return "5.5"; case 5.6: if ("XMLHttpRequest" in window) return "7.0"; return "6.0"; case 5.7: return "7.0"; default: return true; } } if (@_win16 || @_win32 || @_win64) { this.windows = true; this.trident = jscriptVersion(); } else if (@_mac || navigator.platform.indexOf("Mac") >= 0) { // '@_mac' may be 'NaN' even if the platform is Mac, // so we check 'navigator.platform', too. this.mac = true; this.tasman = jscriptVersion(); } if (match = ua.match("MSIE ?(\\d+\\.\\d+)b?;")) { this.ie = match[1]; this['ie' + match[1].charAt(0)] = true; } @else @*/ /* for AppleWebKit */ if (match = ua.match("AppleWebKit/(\\d+(\\.\\d+)*)")) { this.applewebkit = match[1]; this['applewebkit' + match[1].charAt(0)] = true; } /* for Gecko */ else if (typeof(Components) == "object") { if (match = ua.match("Gecko/(\\d{8})")) { this.gecko = match[1]; } else if (navigator.product == "Gecko" && (match = navigator.productSub.match("^(\\d{8})$"))) { this.gecko = match[1]; } } /*@end @*/ if (typeof(opera) == "object" && typeof(opera.version) == "function") { this.opera = opera.version(); this['opera' + this.opera[0] + this.opera[2]] = true; } else if (typeof(opera) == "object" && (match = ua.match("Opera[/ ](\\d+\\.\\d+)"))) { this.opera = match[1]; } else if (this.ie) { } else if (match = ua.match("Safari/(\\d+(\\.\\d+)*)")) { this.safari = match[1]; } else if (match = ua.match("Konqueror/(\\d+(\\.\\d+)*)")) { this.konqueror = match[1]; } else if (ua.indexOf("(compatible;") < 0 && (match = ua.match("^Mozilla/(\\d+\\.\\d+)"))) { this.mozilla = match[1]; if (match = ua.match("\\([^(]*rv:(\\d+(\\.\\d+)*).*?\\)")) this.mozillarv = match[1]; if (match = ua.match("Firefox/(\\d+(\\.\\d+)*)")) { this.firefox = match[1]; } else if (match = ua.match("Netscape\\d?/(\\d+(\\.\\d+)*)")) { this.netscape = match[1]; } } else { this.unknown = true; } if (ua.indexOf("Win 9x 4.90") >= 0) { this.windows = "ME"; } else if (match = ua.match("Win(dows)? ?(NT ?(\\d+\\.\\d+)?|\\d+|XP|ME|Vista)")) { this.windows = match[2]; if (match[3]) { this.winnt = match[3]; } else switch (match[2]) { case "2000": this.winnt = "5.0"; break; case "XP": this.winnt = "5.1"; break; case "Vista": this.winnt = "6.0"; break; } } else if (ua.indexOf("Mac") >= 0) { this.mac = true; } else if (ua.indexOf("Linux") >= 0) { this.linux = true; } else if (match = ua.match("\\w*BSD")) { this.bsd = match[0]; } else if (ua.indexOf("SunOS") >= 0) { this.sunos = true; } } }; /** * pseudo class: Lexer */ var Lexer = function(source) { var proto = Lexer.prototype; var tokens = source.match(proto.regs.token); for (var i = 0, l = tokens.length; i < l; i ++) { if (proto.regs.strip.test(tokens[i])) { tokens.splice(i, 1); } } for (var n in proto) tokens[n] = proto[n]; tokens.index = 0; return tokens; }; Lexer.prototype.regs = { token: /\$?(?:(?![0-9-])[\w-]+:)?(?![0-9-])[\w-]+|\/\/|\.\.|::|\d+(?:\.\d*)?|\.\d+|"[^"]*"|'[^']*'|[!<>]=|(?![0-9-])[\w-]+:\*|\s+|./g, strip: /^\s/ }; Lexer.prototype.peek = function(i) { return this[this.index + (i||0)]; }; Lexer.prototype.next = function() { return this[this.index++]; }; Lexer.prototype.back = function() { this.index--; }; Lexer.prototype.empty = function() { return this.length <= this.index; }; /** * class: Ctx */ var Ctx = function(node, position, last) { this.node = node; this.position = position || 1; this.last = last || 1; }; /** * abstract class: BaseExpr */ var BaseExpr = function() {}; BaseExpr.prototype.number = function(ctx) { var exrs = this.evaluate(ctx); if (exrs.isNodeSet) return exrs.number(); return + exrs; }; BaseExpr.prototype.string = function(ctx) { var exrs = this.evaluate(ctx); if (exrs.isNodeSet) return exrs.string(); return '' + exrs; }; BaseExpr.prototype.bool = function(ctx) { var exrs = this.evaluate(ctx); if (exrs.isNodeSet) return exrs.bool(); return !! exrs; }; /** * abstract class: BaseExprHasPredicates */ var BaseExprHasPredicates = function() {}; BaseExprHasPredicates.parsePredicates = function(lexer, expr) { while (lexer.peek() == '[') { lexer.next(); if (lexer.empty()) { throw Error('missing predicate expr'); } var predicate = BinaryExpr.parse(lexer); expr.predicate(predicate); if (lexer.empty()) { throw Error('unclosed predicate expr'); } if (lexer.next() != ']') { lexer.back(); throw Error('bad token: ' + lexer.next()); } } }; BaseExprHasPredicates.prototyps = new BaseExpr(); BaseExprHasPredicates.prototype.evaluatePredicates = function(nodeset, start) { var predicates, predicate, nodes, node, nodeset, position, reverse; reverse = this.reverse; predicates = this.predicates; nodeset.sort(); for (var i = start || 0, l0 = predicates.length; i < l0; i ++) { predicate = predicates[i]; var deleteIndexes = []; var nodes = nodeset.list(); for (var j = 0, l1 = nodes.length; j < l1; j ++) { position = reverse ? (l1 - j) : (j + 1); exrs = predicate.evaluate(new Ctx(nodes[j], position, l1)); switch (typeof exrs) { case 'number': exrs = (position == exrs); break; case 'string': exrs = !!exrs; break; case 'object': exrs = exrs.bool(); break; } if (!exrs) { deleteIndexes.push(j); } } for (var j = deleteIndexes.length - 1, l1 = 0; j >= l1; j --) { nodeset.del(deleteIndexes[j]); } } return nodeset; }; /** * class: BinaryExpr */ if (!window.BinaryExpr && window.defaultConfig) window.BinaryExpr = null; BinaryExpr = function(op, left, right, datatype) { this.op = op; this.left = left; this.right = right; this.datatype = BinaryExpr.ops[op][2]; this.needContextPosition = left.needContextPosition || right.needContextPosition; this.needContextNode = left.needContextNode || right.needContextNode; // Optimize [@id="foo"] and [@name="bar"] if (this.op == '=') { if (!right.needContextNode && !right.needContextPosition && right.datatype != 'nodeset' && right.datatype != 'void' && left.quickAttr) { this.quickAttr = true; this.attrName = left.attrName; this.attrValueExpr = right; } else if (!left.needContextNode && !left.needContextPosition && left.datatype != 'nodeset' && left.datatype != 'void' && right.quickAttr) { this.quickAttr = true; this.attrName = right.attrName; this.attrValueExpr = left; } } }; BinaryExpr.compare = function(op, comp, left, right, ctx) { var type, lnodes, rnodes, nodes, nodeset, primitive; left = left.evaluate(ctx); right = right.evaluate(ctx); if (left.isNodeSet && right.isNodeSet) { lnodes = left.list(); rnodes = right.list(); for (var i = 0, l0 = lnodes.length; i < l0; i ++) for (var j = 0, l1 = rnodes.length; j < l1; j ++) if (comp(NodeUtil.to('string', lnodes[i]), NodeUtil.to('string', rnodes[j]))) return true; return false; } if (left.isNodeSet || right.isNodeSet) { if (left.isNodeSet) nodeset = left, primitive = right; else nodeset = right, primitive = left; nodes = nodeset.list(); type = typeof primitive; for (var i = 0, l = nodes.length; i < l; i ++) { if (comp(NodeUtil.to(type, nodes[i]), primitive)) return true; } return false; } if (op == '=' || op == '!=') { if (typeof left == 'boolean' || typeof right == 'boolean') { return comp(!!left, !!right); } if (typeof left == 'number' || typeof right == 'number') { return comp(+left, +right); } return comp(left, right); } return comp(+left, +right); }; BinaryExpr.ops = { 'div': [6, function(left, right, ctx) { return left.number(ctx) / right.number(ctx); }, 'number'], 'mod': [6, function(left, right, ctx) { return left.number(ctx) % right.number(ctx); }, 'number'], '*': [6, function(left, right, ctx) { return left.number(ctx) * right.number(ctx); }, 'number'], '+': [5, function(left, right, ctx) { return left.number(ctx) + right.number(ctx); }, 'number'], '-': [5, function(left, right, ctx) { return left.number(ctx) - right.number(ctx); }, 'number'], '<': [4, function(left, right, ctx) { return BinaryExpr.compare('<', function(a, b) { return a < b }, left, right, ctx); }, 'boolean'], '>': [4, function(left, right, ctx) { return BinaryExpr.compare('>', function(a, b) { return a > b }, left, right, ctx); }, 'boolean'], '<=': [4, function(left, right, ctx) { return BinaryExpr.compare('<=', function(a, b) { return a <= b }, left, right, ctx); }, 'boolean'], '>=': [4, function(left, right, ctx) { return BinaryExpr.compare('>=', function(a, b) { return a >= b }, left, right, ctx); }, 'boolean'], '=': [3, function(left, right, ctx) { return BinaryExpr.compare('=', function(a, b) { return a == b }, left, right, ctx); }, 'boolean'], '!=': [3, function(left, right, ctx) { return BinaryExpr.compare('!=', function(a, b) { return a != b }, left, right, ctx); }, 'boolean'], 'and': [2, function(left, right, ctx) { return left.bool(ctx) && right.bool(ctx); }, 'boolean'], 'or': [1, function(left, right, ctx) { return left.bool(ctx) || right.bool(ctx); }, 'boolean'] }; BinaryExpr.parse = function(lexer) { var op, precedence, info, expr, stack = [], index = lexer.index; while (true) { if (lexer.empty()) { throw Error('missing right expression'); } expr = UnaryExpr.parse(lexer); op = lexer.next(); if (!op) { break; } info = this.ops[op]; precedence = info && info[0]; if (!precedence) { lexer.back(); break; } while (stack.length && precedence <= this.ops[stack[stack.length-1]][0]) { expr = new BinaryExpr(stack.pop(), stack.pop(), expr); } stack.push(expr, op); } while (stack.length) { expr = new BinaryExpr(stack.pop(), stack.pop(), expr); } return expr; }; BinaryExpr.prototype = new BaseExpr(); BinaryExpr.prototype.evaluate = function(ctx) { return BinaryExpr.ops[this.op][1](this.left, this.right, ctx); }; BinaryExpr.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'binary: ' + this.op + '\n'; indent += ' '; t += this.left.show(indent); t += this.right.show(indent); return t; }; /** * class: UnaryExpr */ if (!window.UnaryExpr && window.defaultConfig) window.UnaryExpr = null; UnaryExpr = function(op, expr) { this.op = op; this.expr = expr; this.needContextPosition = expr.needContextPosition; this.needContextNode = expr.needContextNode; }; UnaryExpr.ops = { '-': 1 }; UnaryExpr.parse = function(lexer) { var token; if (this.ops[lexer.peek()]) return new UnaryExpr(lexer.next(), UnaryExpr.parse(lexer)); else return UnionExpr.parse(lexer); }; UnaryExpr.prototype = new BaseExpr(); UnaryExpr.prototype.datatype = 'number'; UnaryExpr.prototype.evaluate = function(ctx) { return - this.expr.number(ctx); }; UnaryExpr.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'unary: ' + this.op + '\n'; indent += ' '; t += this.expr.show(indent); return t; }; /** * class: UnionExpr */ if (!window.UnionExpr && window.defaultConfig) window.UnionExpr = null; UnionExpr = function() { this.paths = []; }; UnionExpr.ops = { '|': 1 }; UnionExpr.parse = function(lexer) { var union, expr; expr = PathExpr.parse(lexer); if (!this.ops[lexer.peek()]) return expr; union = new UnionExpr(); union.path(expr); while (true) { if (!this.ops[lexer.next()]) break; if (lexer.empty()) { throw Error('missing next union location path'); } union.path(PathExpr.parse(lexer)); } lexer.back(); return union; }; UnionExpr.prototype = new BaseExpr(); UnionExpr.prototype.datatype = 'nodeset'; UnionExpr.prototype.evaluate = function(ctx) { var paths = this.paths; var nodeset = new NodeSet(); for (var i = 0, l = paths.length; i < l; i ++) { var exrs = paths[i].evaluate(ctx); if (!exrs.isNodeSet) throw Error('PathExpr must be nodeset'); nodeset.merge(exrs); } return nodeset; }; UnionExpr.prototype.path = function(path) { this.paths.push(path); if (path.needContextPosition) { this.needContextPosition = true; } if (path.needContextNode) { this.needContextNode = true; } } UnionExpr.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'union:' + '\n'; indent += ' '; for (var i = 0; i < this.paths.length; i ++) { t += this.paths[i].show(indent); } return t; }; /** * class: PathExpr */ if (!window.PathExpr && window.defaultConfig) window.PathExpr = null; PathExpr = function(filter) { this.filter = filter; this.steps = []; this.datatype = filter.datatype; this.needContextPosition = filter.needContextPosition; this.needContextNode = filter.needContextNode; }; PathExpr.ops = { '//': 1, '/': 1 }; PathExpr.parse = function(lexer) { var op, expr, path, token; if (this.ops[lexer.peek()]) { op = lexer.next(); token = lexer.peek(); if (op == '/' && (lexer.empty() || (token != '.' && token != '..' && token != '@' && token != '*' && !token.match(/(?![0-9])[\w]/)))) { return FilterExpr.root(); } path = new PathExpr(FilterExpr.root()); // RootExpr if (lexer.empty()) { throw Error('missing next location step'); } expr = Step.parse(lexer); path.step(op, expr); } else { expr = FilterExpr.parse(lexer); if (!expr) { expr = Step.parse(lexer); path = new PathExpr(FilterExpr.context()); path.step('/', expr); } else if (!this.ops[lexer.peek()]) return expr; else path = new PathExpr(expr); } while (true) { if (!this.ops[lexer.peek()]) break; op = lexer.next(); if (lexer.empty()) { throw Error('missing next location step'); } path.step(op, Step.parse(lexer)); } return path; }; PathExpr.prototype = new BaseExpr(); PathExpr.prototype.evaluate = function(ctx) { var nodeset = this.filter.evaluate(ctx); if (!nodeset.isNodeSet) throw Exception('Filter nodeset must be nodeset type'); var steps = this.steps; for (var i = 0, l0 = steps.length; i < l0 && nodeset.length; i ++) { var step = steps[i][1]; var reverse = step.reverse; var iter = nodeset.iterator(reverse); var prevNodeset = nodeset; nodeset = null; var node, next; if (!step.needContextPosition && step.axis == 'following') { for (node = iter(); next = iter(); node = next) { // Safari 2 node.contains problem if (uai.applewebkit4) { var contains = false; var ancestor = next; do { if (ancestor == node) { contains = true; break; } } while (ancestor = ancestor.parentNode); if (!contains) break; } else { try { if (!node.contains(next)) break } catch(e) { if (!(next.compareDocumentPosition(node) & 8)) break } } } nodeset = step.evaluate(new Ctx(node)); } else if (!step.needContextPosition && step.axis == 'preceding') { node = iter(); nodeset = step.evaluate(new Ctx(node)); } else { node = iter(); var j = 0; nodeset = step.evaluate(new Ctx(node), false, prevNodeset, j); while (node = iter()) { j ++; nodeset.merge(step.evaluate(new Ctx(node), false, prevNodeset, j)); } } } return nodeset; }; PathExpr.prototype.step = function(op, step) { step.op = op; this.steps.push([op, step]); this.quickAttr = false; if (this.steps.length == 1) { if (op == '/' && step.axis == 'attribute') { var test = step.test; if (!test.notOnlyElement && test.name != '*') { this.quickAttr = true; this.attrName = test.name; } } } }; PathExpr.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'path:' + '\n'; indent += ' '; t += indent + 'filter:' + '\n'; t += this.filter.show(indent + ' '); if (this.steps.length) { t += indent + 'steps:' + '\n'; indent += ' '; for (var i = 0; i < this.steps.length; i ++) { var step = this.steps[i]; t += indent + 'operator: ' + step[0] + '\n'; t += step[1].show(indent); } } return t; }; /** * class: FilterExpr */ if (!window.FilterExpr && window.defaultConfig) window.FilterExpr = null; FilterExpr = function(primary) { this.primary = primary; this.predicates = []; this.datatype = primary.datatype; this.needContextPosition = primary.needContextPosition; this.needContextNode = primary.needContextNode; }; FilterExpr.parse = function(lexer) { var expr, filter, token, ch; token = lexer.peek(); ch = token.charAt(0); switch (ch) { case '$': expr = VariableReference.parse(lexer); break; case '(': lexer.next(); expr = BinaryExpr.parse(lexer); if (lexer.empty()) { throw Error('unclosed "("'); } if (lexer.next() != ')') { lexer.back(); throw Error('bad token: ' + lexer.next()); } break; case '"': case "'": expr = Literal.parse(lexer); break; default: if (!isNaN(+token)) { expr = Number.parse(lexer); } else if (NodeType.types[token]) { return null; } else if (ch.match(/(?![0-9])[\w]/) && lexer.peek(1) == '(') { expr = FunctionCall.parse(lexer); } else { return null; } break; } if (lexer.peek() != '[') return expr; filter = new FilterExpr(expr); BaseExprHasPredicates.parsePredicates(lexer, filter); return filter; }; FilterExpr.root = function() { return new FunctionCall('root-node'); }; FilterExpr.context = function() { return new FunctionCall('context-node'); }; FilterExpr.prototype = new BaseExprHasPredicates(); FilterExpr.prototype.evaluate = function(ctx) { var nodeset = this.primary.evaluate(ctx); if(!nodeset.isNodeSet) { if (this.predicates.length) throw Error( 'Primary result must be nodeset type ' + 'if filter have predicate expression'); return nodeset; } return this.evaluatePredicates(nodeset); }; FilterExpr.prototype.predicate = function(predicate) { this.predicates.push(predicate); }; FilterExpr.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'filter: ' + '\n'; indent += ' '; t += this.primary.show(indent); if (this.predicates.length) { t += indent + 'predicates: ' + '\n'; indent += ' '; for (var i = 0; i < this.predicates.length; i ++) { t += this.predicates[i].show(indent); } } return t; }; if (!window.NodeUtil && window.defaultConfig) window.NodeUtil = null; NodeUtil = { to: function(valueType, node) { var type = node.nodeType; /*@cc_on if (type == 1 && node.nodeName.toLowerCase() == 'title') { t = node.text; } else @*/ if (type == 9 || type == 1) { if (type == 9) { node = node.documentElement; } else { node = node.firstChild; } for (var t = '', stack = [], i = 0; node;) { do { if (node.nodeType != 1) { t += node.nodeValue; } /*@cc_on else if (node.nodeName.toLowerCase() == 'title') { t += node.text; } @*/ stack[i++] = node; // push } while (node = node.firstChild); while (i && !(node = stack[--i].nextSibling)) {} } } else { var t = node.nodeValue; } switch (valueType) { case 'number': return + t; case 'boolean': return !! t; default: return t; } }, attrPropMap: { name: 'name', 'class': 'className', dir: 'dir', id: 'id', name: 'name', title: 'title' }, attrMatch: function(node, attrName, attrValue) { /*@cc_on @if (@_jscript) var propName = NodeUtil.attrPropMap[attrName]; if (!attrName || attrValue == null && ( propName && node[propName] || !propName && node.getAttribute && node.getAttribute(attrName) ) || attrValue != null && ( propName && node[propName] == attrValue || !propName && node.getAttribute && node.getAttribute(attrName) == attrValue )) { @else @*/ if (!attrName || attrValue == null && node.hasAttribute && node.hasAttribute(attrName) || attrValue != null && node.getAttribute && node.getAttribute(attrName) == attrValue) { /*@end @*/ return true; } else { return false; } }, getDescendantNodes: function(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex) { if (prevNodeset) { prevNodeset.delDescendant(node, prevIndex); } /*@cc_on if (!test.notOnlyElement || test.type == 8 || (attrName && test.type == 0)) { var all = node.all; if (!all) { return nodeset; } var name = test.name; if (test.type == 8) name = '!'; else if (test.type == 0) name = '*'; if (name != '*') { all = all.tags(name); if (!all) { return nodeset; } } if (attrName) { var result = [] var i = 0; if (attrValue != null && (attrName == 'id' || attrName == 'name')) { all = all[attrValue]; if (!all) { return nodeset; } if (!all.length) { all = [all]; } } while (node = all[i++]) { if (NodeUtil.attrMatch(node, attrName, attrValue)) result.push(node); } all = result; } var i = 0; while (node = all[i++]) { if (name != '*' || node.tagName != '!') { nodeset.push(node); } } return nodeset; } (function (parent) { var g = arguments.callee; var node = parent.firstChild; if (node) { for (; node; node = node.nextSibling) { if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node)) nodeset.push(node); } g(node); } } })(node); return nodeset; @*/ if (attrValue && attrName == 'id' && node.getElementById) { node = node.getElementById(attrValue); if (node && test.match(node)) { nodeset.push(node); } } else if (attrValue && attrName == 'name' && node.getElementsByName) { var nodes = node.getElementsByName(attrValue); for (var i = 0, l = nodes.length; i < l; i ++) { node = nodes[i]; if (uai.opera ? (node.name == attrValue && test.match(node)) : test.match(node)) { nodeset.push(node); } } } else if (attrValue && attrName == 'class' && node.getElementsByClassName) { var nodes = node.getElementsByClassName(attrValue); for (var i = 0, l = nodes.length; i < l; i ++) { node = nodes[i]; if (node.className == attrValue && test.match(node)) { nodeset.push(node); } } } else if (test.notOnlyElement) { (function (parent) { var f = arguments.callee; for (var node = parent.firstChild; node; node = node.nextSibling) { if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node.nodeType)) nodeset.push(node); } f(node); } })(node); } else { var name = test.name; if (node.getElementsByTagName) { var nodes = node.getElementsByTagName(name); if (nodes) { var i = 0; while (node = nodes[i++]) { if (NodeUtil.attrMatch(node, attrName, attrValue)) nodeset.push(node); } } } } return nodeset; }, getChildNodes: function(test, node, nodeset, attrName, attrValue) { /*@cc_on var children; if ((!test.notOnlyElement || test.type == 8 || (attrName && test.type == 0)) && (children = node.children)) { var name, elm; name = test.name; if (test.type == 8) name = '!'; else if (test.type == 0) name = '*'; if (name != '*') { children = children.tags(name); if (!children) { return nodeset; } } if (attrName) { var result = [] var i = 0; if (attrName == 'id' || attrName == 'name') { children = children[attrValue]; if (!children) { return nodeset; } if (!children.length) { children = [children]; } } while (node = children[i++]) { if (NodeUtil.attrMatch(node, attrName, attrValue)) result.push(node); } children = result; } var i = 0; while (node = children[i++]) { if (name != '*' || node.tagName != '!') { nodeset.push(node); } } return nodeset; } for (var i = 0, node = node.firstChild; node; i++, node = node.nextSibling) { if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node)) nodeset.push(node); } } return nodeset; @*/ for (var node = node.firstChild; node; node = node.nextSibling) { if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node)) nodeset.push(node); } } return nodeset; } }; /*@cc_on var AttributeWrapper = function(node, parent, sourceIndex) { this.node = node; this.nodeType = 2; this.nodeValue = node.nodeValue; this.nodeName = node.nodeName; this.parentNode = parent; this.ownerElement = parent; this.parentSourceIndex = sourceIndex; }; @*/ /** * class: Step */ if (!window.Step && window.defaultConfig) window.Step = null; Step = function(axis, test) { // TODO check arguments and throw axis error this.axis = axis; this.reverse = Step.axises[axis][0]; this.func = Step.axises[axis][1]; this.test = test; this.predicates = []; this._quickAttr = Step.axises[axis][2] }; Step.axises = { ancestor: [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) { while (node = node.parentNode) { if (prevNodeset && node.nodeType == 1) { prevNodeset.reserveDelByNode(node, prevIndex, true); } if (test.match(node)) nodeset.unshift(node); } return nodeset; }], 'ancestor-or-self': [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) { do { if (prevNodeset && node.nodeType == 1) { prevNodeset.reserveDelByNode(node, prevIndex, true); } if (test.match(node)) nodeset.unshift(node); } while (node = node.parentNode) return nodeset; }], attribute: [false, function(test, node, nodeset) { var attrs = node.attributes; if (attrs) { /*@cc_on var sourceIndex = node.sourceIndex; @*/ if ((test.notOnlyElement && test.type == 0) || test.name == '*') { for (var i = 0, l = attrs.length; i < l; i ++) { var attr = attrs[i]; /*@cc_on @if (@_jscript) if (attr.nodeValue) { nodeset.push(new AttributeWrapper(attr, node, sourceIndex)); } @else @*/ nodeset.push(attr); /*@end @*/ } } else { var attr = attrs.getNamedItem(test.name) /*@cc_on @if (@_jscript) if (attr && attr.nodeValue) { attr = new AttributeWrapper(attr, node, sourceIndex);; @else @*/ if (attr) { /*@end @*/ nodeset.push(attr); } } } return nodeset; }], child: [false, NodeUtil.getChildNodes, true], descendant: [false, NodeUtil.getDescendantNodes, true], 'descendant-or-self': [false, function(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex) { if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node)) nodeset.push(node); } return NodeUtil.getDescendantNodes(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex); }, true], following: [false, function(test, node, nodeset, attrName, attrValue) { do { var child = node; while (child = child.nextSibling) { if (NodeUtil.attrMatch(child, attrName, attrValue)) { if (test.match(child)) nodeset.push(child); } nodeset = NodeUtil.getDescendantNodes(test, child, nodeset, attrName, attrValue); } } while (node = node.parentNode); return nodeset; }, true], 'following-sibling': [false, function(test, node, nodeset, _, __, prevNodeset, prevIndex) { while (node = node.nextSibling) { if (prevNodeset && node.nodeType == 1) { prevNodeset.reserveDelByNode(node, prevIndex); } if (test.match(node)) { nodeset.push(node); } } return nodeset; }], namespace: [false, function(test, node, nodeset) { // not implemented return nodeset; }], parent: [false, function(test, node, nodeset) { if (node.nodeType == 9) { return nodeset; } if (node.nodeType == 2) { nodeset.push(node.ownerElement); return nodeset; } var node = node.parentNode; if (test.match(node)) nodeset.push(node); return nodeset; }], preceding: [true, function(test, node, nodeset, attrName, attrValue) { var parents = []; do { parents.unshift(node); } while (node = node.parentNode); for (var i = 1, l0 = parents.length; i < l0; i ++) { var siblings = []; node = parents[i]; while (node = node.previousSibling) { siblings.unshift(node); } for (var j = 0, l1 = siblings.length; j < l1; j ++) { node = siblings[j]; if (NodeUtil.attrMatch(node, attrName, attrValue)) { if (test.match(node)) nodeset.push(node); } nodeset = NodeUtil.getDescendantNodes(test, node, nodeset, attrName, attrValue); } } return nodeset; }, true], 'preceding-sibling': [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) { while (node = node.previousSibling) { if (prevNodeset && node.nodeType == 1) { prevNodeset.reserveDelByNode(node, prevIndex, true); } if (test.match(node)) { nodeset.unshift(node) } } return nodeset; }], self: [false, function(test, node, nodeset) { if (test.match(node)) nodeset.push(node); return nodeset; }] }; Step.parse = function(lexer) { var axis, test, step, token; if (lexer.peek() == '.') { step = this.self(); lexer.next(); } else if (lexer.peek() == '..') { step = this.parent(); lexer.next(); } else { if (lexer.peek() == '@') { axis = 'attribute'; lexer.next(); if (lexer.empty()) { throw Error('missing attribute name'); } } else { if (lexer.peek(1) == '::') { if (!lexer.peek().charAt(0).match(/(?![0-9])[\w]/)) { throw Error('bad token: ' + lexer.next()); } axis = lexer.next(); lexer.next(); if (!this.axises[axis]) { throw Error('invalid axis: ' + axis); } if (lexer.empty()) { throw Error('missing node name'); } } else { axis = 'child'; } } token = lexer.peek(); if (!token.charAt(0).match(/(?![0-9])[\w]/)) { if (token == '*') { test = NameTest.parse(lexer) } else { throw Error('bad token: ' + lexer.next()); } } else { if (lexer.peek(1) == '(') { if (!NodeType.types[token]) { throw Error('invalid node type: ' + token); } test = NodeType.parse(lexer) } else { test = NameTest.parse(lexer); } } step = new Step(axis, test); } BaseExprHasPredicates.parsePredicates(lexer, step); return step; }; Step.self = function() { return new Step('self', new NodeType('node')); }; Step.parent = function() { return new Step('parent', new NodeType('node')); }; Step.prototype = new BaseExprHasPredicates(); Step.prototype.evaluate = function(ctx, special, prevNodeset, prevIndex) { var node = ctx.node; var reverse = false; if (!special && this.op == '//') { if (!this.needContextPosition && this.axis == 'child') { if (this.quickAttr) { var attrValue = this.attrValueExpr ? this.attrValueExpr.string(ctx) : null; var nodeset = NodeUtil.getDescendantNodes(this.test, node, new NodeSet(), this.attrName, attrValue, prevNodeset, prevIndex); nodeset = this.evaluatePredicates(nodeset, 1); } else { var nodeset = NodeUtil.getDescendantNodes(this.test, node, new NodeSet(), null, null, prevNodeset, prevIndex); nodeset = this.evaluatePredicates(nodeset); } } else { var step = new Step('descendant-or-self', new NodeType('node')); var nodes = step.evaluate(ctx, false, prevNodeset, prevIndex).list(); var nodeset = null; step.op = '/'; for (var i = 0, l = nodes.length; i < l; i ++) { if (!nodeset) { nodeset = this.evaluate(new Ctx(nodes[i]), true); } else { nodeset.merge(this.evaluate(new Ctx(nodes[i]), true)); } } nodeset = nodeset || new NodeSet(); } } else { if (this.needContextPosition) { prevNodeset = null; prevIndex = null; } if (this.quickAttr) { var attrValue = this.attrValueExpr ? this.attrValueExpr.string(ctx) : null; var nodeset = this.func(this.test, node, new NodeSet(), this.attrName, attrValue, prevNodeset, prevIndex); nodeset = this.evaluatePredicates(nodeset, 1); } else { var nodeset = this.func(this.test, node, new NodeSet(), null, null, prevNodeset, prevIndex); nodeset = this.evaluatePredicates(nodeset); } if (prevNodeset) { prevNodeset.doDel(); } } return nodeset; }; Step.prototype.predicate = function(predicate) { this.predicates.push(predicate); if (predicate.needContextPosition || predicate.datatype == 'number'|| predicate.datatype == 'void') { this.needContextPosition = true; } if (this._quickAttr && this.predicates.length == 1 && predicate.quickAttr) { var attrName = predicate.attrName; /*@cc_on @if (@_jscript) this.attrName = attrName.toLowerCase(); @else @*/ this.attrName = attrName; /*@end @*/ this.attrValueExpr = predicate.attrValueExpr; this.quickAttr = true; } }; Step.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'step: ' + '\n'; indent += ' '; if (this.axis) t += indent + 'axis: ' + this.axis + '\n'; t += this.test.show(indent); if (this.predicates.length) { t += indent + 'predicates: ' + '\n'; indent += ' '; for (var i = 0; i < this.predicates.length; i ++) { t += this.predicates[i].show(indent); } } return t; }; /** * NodeType */ if (!window.NodeType && window.defaultConfig) window.NodeType = null; NodeType = function(name, literal) { this.name = name; this.literal = literal; switch (name) { case 'comment': this.type = 8; break; case 'text': this.type = 3; break; case 'processing-instruction': this.type = 7; break; case 'node': this.type = 0; break; } }; NodeType.types = { 'comment':1, 'text':1, 'processing-instruction':1, 'node':1 }; NodeType.parse = function(lexer) { var type, literal, ch; type = lexer.next(); lexer.next(); if (lexer.empty()) { throw Error('bad nodetype'); } ch = lexer.peek().charAt(0); if (ch == '"' || ch == "'") { literal = Literal.parse(lexer); } if (lexer.empty()) { throw Error('bad nodetype'); } if (lexer.next() != ')') { lexer.back(); throw Error('bad token ' + lexer.next()); } return new NodeType(type, literal); }; NodeType.prototype = new BaseExpr(); NodeType.prototype.notOnlyElement = true; NodeType.prototype.match = function(node) { return !this.type || this.type == node.nodeType; }; NodeType.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'nodetype: ' + this.type + '\n'; if (this.literal) { indent += ' '; t += this.literal.show(indent); } return t; }; /** * NodeType */ if (!window.NameTest && window.defaultConfig) window.NameTest = null; NameTest = function(name) { this.name = name.toLowerCase(); }; NameTest.parse = function(lexer) { if (lexer.peek() != '*' && lexer.peek(1) == ':' && lexer.peek(2) == '*') { return new NameTest(lexer.next() + lexer.next() + lexer.next()); } return new NameTest(lexer.next()); }; NameTest.prototype = new BaseExpr(); NameTest.prototype.match = function(node) { var type = node.nodeType; if (type == 1 || type == 2) { if (this.name == '*' || this.name == node.nodeName.toLowerCase()) { return true; } } return false; }; NameTest.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'nametest: ' + this.name + '\n'; return t; }; /** * class: VariableRefernce */ if (!window.VariableReference && window.defaultConfig) window.VariableReference = null; VariableReference = function(name) { this.name = name.substring(1); }; VariableReference.parse = function(lexer) { var token = lexer.next(); if (token.length < 2) { throw Error('unnamed variable reference'); } return new VariableReference(token) }; VariableReference.prototype = new BaseExpr(); VariableReference.prototype.datatype = 'void'; VariableReference.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'variable: ' + this.name + '\n'; return t; }; /** * class: Literal */ if (!window.Literal && window.defaultConfig) window.Literal = null; Literal = function(text) { this.text = text.substring(1, text.length - 1); }; Literal.parse = function(lexer) { var token = lexer.next(); if (token.length < 2) { throw Error('unclosed literal string'); } return new Literal(token) }; Literal.prototype = new BaseExpr(); Literal.prototype.datatype = 'string'; Literal.prototype.evaluate = function(ctx) { return this.text; }; Literal.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'literal: ' + this.text + '\n'; return t; }; /** * class: Number */ if (!window.Number && window.defaultConfig) window.Number = null; Number = function(digit) { this.digit = +digit; }; Number.parse = function(lexer) { return new Number(lexer.next()); }; Number.prototype = new BaseExpr(); Number.prototype.datatype = 'number'; Number.prototype.evaluate = function(ctx) { return this.digit; }; Number.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'number: ' + this.digit + '\n'; return t; }; /** * class: FunctionCall */ if (!window.FunctionCall && window.defaultConfig) window.FunctionCall = null; FunctionCall = function(name) { var info = FunctionCall.funcs[name]; this.name = name; this.func = info[0]; this.args = []; this.datatype = info[1]; if (info[2]) { this.needContextPosition = true; } this.needContextNodeInfo = info[3]; this.needContextNode = this.needContextNodeInfo[0] }; FunctionCall.funcs = { // Original Function 'context-node': [function() { if (arguments.length != 0) { throw Error('Function context-node expects ()'); } var ns; ns = new NodeSet(); ns.push(this.node); return ns; }, 'nodeset', false, [true]], // Original Function 'root-node': [function() { if (arguments.length != 0) { throw Error('Function root-node expects ()'); } var ns, ctxn; ns = new NodeSet(); ctxn = this.node; if (ctxn.nodeType == 9) ns.push(ctxn); else ns.push(ctxn.ownerDocument); return ns; }, 'nodeset', false, []], last: [function() { if (arguments.length != 0) { throw Error('Function last expects ()'); } return this.last; }, 'number', true, []], position: [function() { if (arguments.length != 0) { throw Error('Function position expects ()'); } return this.position; }, 'number', true, []], count: [function(ns) { if (arguments.length != 1 || !(ns = ns.evaluate(this)).isNodeSet) { throw Error('Function count expects (nodeset)'); } return ns.length; }, 'number', false, []], id: [function(s) { var ids, ns, i, id, elm, ctxn, doc; if (arguments.length != 1) { throw Error('Function id expects (object)'); } ctxn = this.node; if (ctxn.nodeType == 9) doc = ctxn; else doc = ctxn.ownerDocument; /*@cc_on all = doc.all; @*/ s = s.string(this); ids = s.split(/\s+/); ns = new NodeSet(); for (i = 0, l = ids.length; i < l; i ++) { id = ids[i]; /*@cc_on @if (@_jscript) elm = all[id]; if (elm) { if (elm.length) { var elms = elm; for (var j = 0, l0 = elms.length; j < l0; j ++) { var elem = elms[j]; if (id == elem.id) { ns.push(elem); break; } } } else if (id == elm.id) { ns.push(elm) } } @else @*/ elm = doc.getElementById(id); if (uai.opera && elm.id != id) { var elms = doc.getElementsByName(id); for (var j = 0, l0 = elms.length; j < l0; j ++) { elm = elms[j]; if (elm.id == id) { ns.push(elm); } } } else { if (elm) ns.push(elm) } /*@end @*/ } ns.isSorted = false; return ns; }, 'nodeset', false, []], 'local-name': [function(ns) { var nd; switch (arguments.length) { case 0: nd = this.node; break; case 1: if ((ns = ns.evaluate(this)).isNodeSet) { nd = ns.first(); break; } default: throw Error('Function local-name expects (nodeset?)'); break; } return '' + nd.nodeName.toLowerCase(); }, 'string', false, [true, false]], name: [function(ns) { // not implemented return FunctionCall.funcs['local-name'][0].apply(this, arguments); }, 'string', false, [true, false]], 'namespace-uri': [function(ns) { // not implemented return ''; }, 'string', false, [true, false]], string: [function(s) { switch (arguments.length) { case 0: s = NodeUtil.to('string', this.node); break; case 1: s = s.string(this); break; default: throw Error('Function string expects (object?)'); break; } return s; }, 'string', false, [true, false]], concat: [function(s1, s2) { if (arguments.length < 2) { throw Error('Function concat expects (string, string[, ...])'); } for (var t = '', i = 0, l = arguments.length; i < l; i ++) { t += arguments[i].string(this); } return t; }, 'string', false, []], 'starts-with': [function(s1, s2) { if (arguments.length != 2) { throw Error('Function starts-with expects (string, string)'); } s1 = s1.string(this); s2 = s2.string(this); return s1.indexOf(s2) == 0; }, 'boolean', false, []], contains: [function(s1, s2) { if (arguments.length != 2) { throw Error('Function contains expects (string, string)'); } s1 = s1.string(this); s2 = s2.string(this); return s1.indexOf(s2) != -1; }, 'boolean', false, []], substring: [function(s, n1, n2) { var a1, a2; s = s.string(this); n1 = n1.number(this); switch (arguments.length) { case 2: n2 = s.length - n1 + 1; break; case 3: n2 = n2.number(this); break; default: throw Error('Function substring expects (string, string)'); break; } n1 = Math.round(n1); n2 = Math.round(n2); a1 = n1 - 1; a2 = n1 + n2 - 1; if (a2 == Infinity) { return s.substring(a1 < 0 ? 0 : a1); } else { return s.substring(a1 < 0 ? 0 : a1, a2) } }, 'string', false, []], 'substring-before': [function(s1, s2) { var n; if (arguments.length != 2) { throw Error('Function substring-before expects (string, string)'); } s1 = s1.string(this); s2 = s2.string(this); n = s1.indexOf(s2); if (n == -1) return ''; return s1.substring(0, n); }, 'string', false, []], 'substring-after': [function(s1, s2) { if (arguments.length != 2) { throw Error('Function substring-after expects (string, string)'); } s1 = s1.string(this); s2 = s2.string(this); var n = s1.indexOf(s2); if (n == -1) return ''; return s1.substring(n + s2.length); }, 'string', false, []], 'string-length': [function(s) { switch (arguments.length) { case 0: s = NodeUtil.to('string', this.node); break; case 1: s = s.string(this); break; default: throw Error('Function string-length expects (string?)'); break; } return s.length; }, 'number', false, [true, false]], 'normalize-space': [function(s) { switch (arguments.length) { case 0: s = NodeUtil.to('string', this.node); break; case 1: s = s.string(this); break; default: throw Error('Function normalize-space expects (string?)'); break; } return s.replace(/\s+/g, ' ').replace(/^ /, '').replace(/ $/, ''); }, 'string', false, [true, false]], translate: [function(s1, s2, s3) { if (arguments.length != 3) { throw Error('Function translate expects (string, string, string)'); } s1 = s1.string(this); s2 = s2.string(this); s3 = s3.string(this); var map = []; for (var i = 0, l = s2.length; i < l; i ++) { var ch = s2.charAt(i); if (!map[ch]) map[ch] = s3.charAt(i) || ''; } for (var t = '', i = 0, l = s1.length; i < l; i ++) { var ch = s1.charAt(i); var replace = map[ch] t += (replace != undefined) ? replace : ch; } return t; }, 'string', false, []], 'boolean': [function(b) { if (arguments.length != 1) { throw Error('Function boolean expects (object)'); } return b.bool(this) }, 'boolean', false, []], not: [function(b) { if (arguments.length != 1) { throw Error('Function not expects (object)'); } return !b.bool(this) }, 'boolean', false, []], 'true': [function() { if (arguments.length != 0) { throw Error('Function true expects ()'); } return true; }, 'boolean', false, []], 'false': [function() { if (arguments.length != 0) { throw Error('Function false expects ()'); } return false; }, 'boolean', false, []], lang: [function(s) { // not implemented return false; }, 'boolean', false, []], number: [function(n) { switch (arguments.length) { case 0: n = NodeUtil.to('number', this.node); break; case 1: n = n.number(this); break; default: throw Error('Function number expects (object?)'); break; } return n; }, 'number', false, [true, false]], sum: [function(ns) { var nodes, n, i, l; if (arguments.length != 1 || !(ns = ns.evaluate(this)).isNodeSet) { throw Error('Function sum expects (nodeset)'); } nodes = ns.list(); n = 0; for (i = 0, l = nodes.length; i < l; i ++) { n += NodeUtil.to('number', nodes[i]); } return n; }, 'number', false, []], floor: [function(n) { if (arguments.length != 1) { throw Error('Function floor expects (number)'); } n = n.number(this); return Math.floor(n); }, 'number', false, []], ceiling: [function(n) { if (arguments.length != 1) { throw Error('Function ceiling expects (number)'); } n = n.number(this); return Math.ceil(n); }, 'number', false, []], round: [function(n) { if (arguments.length != 1) { throw Error('Function round expects (number)'); } n = n.number(this); return Math.round(n); }, 'number', false, []] }; FunctionCall.parse = function(lexer) { var expr, func = new FunctionCall(lexer.next()); lexer.next(); while (lexer.peek() != ')') { if (lexer.empty()) { throw Error('missing function argument list'); } expr = BinaryExpr.parse(lexer); func.arg(expr); if (lexer.peek() != ',') break; lexer.next(); } if (lexer.empty()) { throw Error('unclosed function argument list'); } if (lexer.next() != ')') { lexer.back(); throw Error('bad token: ' + lexer.next()); } return func }; FunctionCall.prototype = new BaseExpr(); FunctionCall.prototype.evaluate = function (ctx) { return this.func.apply(ctx, this.args); }; FunctionCall.prototype.arg = function(arg) { this.args.push(arg); if (arg.needContextPosition) { this.needContextPosition = true; } var args = this.args; if (arg.needContextNode) { args.needContexNode = true; } this.needContextNode = args.needContextNode || this.needContextNodeInfo[args.length]; }; FunctionCall.prototype.show = function(indent) { indent = indent || ''; var t = ''; t += indent + 'function: ' + this.name + '\n'; indent += ' '; if (this.args.length) { t += indent + 'arguments: ' + '\n'; indent += ' '; for (var i = 0; i < this.args.length; i ++) { t += this.args[i].show(indent); } } return t; }; /*@cc_on @if (@_jscript) var NodeWrapper = function(node, sourceIndex, subIndex, attributeName) { this.node = node; this.nodeType = node.nodeType; this.sourceIndex = sourceIndex; this.subIndex = subIndex; this.attributeName = attributeName || ''; this.order = String.fromCharCode(sourceIndex) + String.fromCharCode(subIndex) + attributeName; }; NodeWrapper.prototype.toString = function() { return this.order; }; @else @*/ var NodeID = { uuid: 1, get: function(node) { return node.__jsxpath_id__ || (node.__jsxpath_id__ = this.uuid++); } }; /*@end @*/ if (!window.NodeSet && window.defaultConfig) window.NodeSet = null; NodeSet = function() { this.length = 0; this.nodes = []; this.seen = {}; this.idIndexMap = null; this.reserveDels = []; }; NodeSet.prototype.isNodeSet = true; NodeSet.prototype.isSorted = true; /*@_cc_on NodeSet.prototype.shortcut = true; @*/ NodeSet.prototype.merge = function(nodeset) { this.isSorted = false; if (nodeset.only) { return this.push(nodeset.only); } if (this.only){ var only = this.only; delete this.only; this.push(only); this.length --; } var nodes = nodeset.nodes; for (var i = 0, l = nodes.length; i < l; i ++) { this._add(nodes[i]); } }; NodeSet.prototype.sort = function() { if (this.only) return; if (this.sortOff) return; if (!this.isSorted) { this.isSorted = true; this.idIndexMap = null; /*@cc_on if (this.shortcut) { this.nodes.sort(); } else { this.nodes.sort(function(a, b) { var result; result = a.sourceIndex - b.sourceIndex; if (result == 0) return a.subIndex - a.subIndex; else return result; }); } return; @*/ var nodes = this.nodes; nodes.sort(function(a, b) { if (a == b) return 0; if (a.compareDocumentPosition) { var result = a.compareDocumentPosition(b); if (result & 2) return 1; if (result & 4) return -1; return 0; } else { var node1 = a, node2 = b, ancestor1 = a, ancestor2 = b, deep1 = 0, deep2 = 0; while(ancestor1 = ancestor1.parentNode) deep1 ++; while(ancestor2 = ancestor2.parentNode) deep2 ++; // same deep if (deep1 > deep2) { while (deep1-- != deep2) node1 = node1.parentNode; if (node1 == node2) return 1; } else if (deep2 > deep1) { while (deep2-- != deep1) node2 = node2.parentNode; if (node1 == node2) return -1; } while ((ancestor1 = node1.parentNode) != (ancestor2 = node2.parentNode)) { node1 = ancestor1; node2 = ancestor2; } // node1 is node2's sibling while (node1 = node1.nextSibling) if (node1 == node2) return -1; return 1; } }); } }; /*@cc_on @if (@_jscript) NodeSet.prototype.sourceOffset = 1; NodeSet.prototype.subOffset = 2; NodeSet.prototype.createWrapper = function(node) { var parent, child, attributes, attributesLength, sourceIndex, subIndex, attributeName; sourceIndex = node.sourceIndex; if (typeof sourceIndex != 'number') { type = node.nodeType; switch (type) { case 2: parent = node.parentNode; sourceIndex = node.parentSourceIndex; subIndex = -1; attributeName = node.nodeName; break; case 9: subIndex = -2; sourceIndex = -1; break; default: child = node; subIndex = 0; do { subIndex ++; sourceIndex = child.sourceIndex; if (sourceIndex) { parent = child; child = child.lastChild; if (!child) { child = parent; break; } subIndex ++; } } while (child = child.previousSibling); if (!sourceIndex) { sourceIndex = node.parentNode.sourceIndex; } break; } } else { subIndex = -2; } sourceIndex += this.sourceOffset; subIndex += this.subOffset; return new NodeWrapper(node, sourceIndex, subIndex, attributeName); }; NodeSet.prototype.reserveDelBySourceIndexAndSubIndex = function(sourceIndex, subIndex, offset, reverse) { var map = this.createIdIndexMap(); var index; if ((map = map[sourceIndex]) && (index = map[subIndex])) { if (reverse && (this.length - offset - 1) > index || !reverse && offset < index) { var obj = { value: index, order: String.fromCharCode(index), toString: function() { return this.order }, valueOf: function() { return this.value } }; this.reserveDels.push(obj); } } }; @else @*/ NodeSet.prototype.reserveDelByNodeID = function(id, offset, reverse) { var map = this.createIdIndexMap(); var index; if (index = map[id]) { if (reverse && (this.length - offset - 1) > index || !reverse && offset < index) { var obj = { value: index, order: String.fromCharCode(index), toString: function() { return this.order }, valueOf: function() { return this.value } }; this.reserveDels.push(obj); } } }; /*@end @*/ NodeSet.prototype.reserveDelByNode = function(node, offset, reverse) { /*@cc_on @if (@_jscript) node = this.createWrapper(node); this.reserveDelBySourceIndexAndSubIndex(node.sourceIndex, node.subIndex, offset, reverse); @else @*/ this.reserveDelByNodeID(NodeID.get(node), offset, reverse); /*@end @*/ }; NodeSet.prototype.doDel = function() { if (!this.reserveDels.length) return; if (this.length < 0x10000) { var dels = this.reserveDels.sort(function(a, b) { return b - a }); } else { var dels = this.reserveDels.sort(function(a, b) { return b - a }); } for (var i = 0, l = dels.length; i < l; i ++) { this.del(dels[i]); } this.reserveDels = []; this.idIndexMap = null; }; NodeSet.prototype.createIdIndexMap = function() { if (this.idIndexMap) { return this.idIndexMap; } else { var map = this.idIndexMap = {}; var nodes = this.nodes; for (var i = 0, l = nodes.length; i < l; i ++) { var node = nodes[i]; /*@cc_on @if (@_jscript) var sourceIndex = node.sourceIndex; var subIndex = node.subIndex; if (!map[sourceIndex]) map[sourceIndex] = {}; map[sourceIndex][subIndex] = i; @else @*/ var id = NodeID.get(node); map[id] = i; /*@end @*/ } return map; } }; NodeSet.prototype.del = function(index) { this.length --; if (this.only) { delete this.only; } else { var node = this.nodes.splice(index, 1)[0]; if (this._first == node) { delete this._first; delete this._firstSourceIndex; delete this._firstSubIndex; } /*@cc_on @if (@_jscript) delete this.seen[node.sourceIndex][node.subIndex]; @else @*/ delete this.seen[NodeID.get(node)]; /*@end @*/ } }; NodeSet.prototype.delDescendant = function(elm, offset) { if (this.only) return; var nodeType = elm.nodeType; if (nodeType != 1 && nodeType != 9) return; if (uai.applewebkit4) return; // element || document if (!elm.contains) { if (nodeType == 1) { var _elm = elm; elm = { contains: function(node) { return node.compareDocumentPosition(_elm) & 8; } }; } else { // document elm = { contains: function() { return true; } }; } } var nodes = this.nodes; for (var i = offset + 1; i < nodes.length; i ++) { /*@cc_on @if (@_jscript) if (nodes[i].node.nodeType == 1 && elm.contains(nodes[i].node)) { @else @*/ if (elm.contains(nodes[i])) { /*@end @*/ this.del(i); i --; } } }; NodeSet.prototype._add = function(node, reverse) { /*@cc_on @if (@_jscript) var first, firstSourceIndex, firstSubIndex, sourceIndex, subIndex, attributeName; sourceIndex = node.sourceIndex; subIndex = node.subIndex; attributeName = node.attributeName; seen = this.seen; seen = seen[sourceIndex] || (seen[sourceIndex] = {}); if (node.nodeType == 2) { seen = seen[subIndex] || (seen[subIndex] = {}); if (seen[attributeName]) { return true; } seen[attributeName] = true; } else { if (seen[subIndex]) { return true; } seen[subIndex] = true; } if (sourceIndex >= 0x10000 || subIndex >= 0x10000) { this.shortcut = false; } // if this._first is undefined and this.nodes is not empty // then first node shortcut is disabled. if (this._first || this.nodes.length == 0) { first = this._first; firstSourceIndex = this._firstSourceIndex; firstSubIndex = this._firstSubIndex; if (!first || firstSourceIndex > sourceIndex || (firstSourceIndex == sourceIndex && firstSubIndex > subIndex)) { this._first = node; this._firstSourceIndex = sourceIndex; this._firstSubIndex = subIndex } } @else @*/ var seen = this.seen; var id = NodeID.get(node); if (seen[id]) return true; seen[id] = true; /*@end @*/ this.length++; if (reverse) this.nodes.unshift(node); else this.nodes.push(node); }; NodeSet.prototype.unshift = function(node) { if (!this.length) { this.length ++; this.only = node; return } if (this.only){ var only = this.only; delete this.only; this.unshift(only); this.length --; } /*@cc_on node = this.createWrapper(node); @*/ return this._add(node, true); }; NodeSet.prototype.push = function(node) { if (!this.length) { this.length ++; this.only = node; return; } if (this.only) { var only = this.only; delete this.only; this.push(only); this.length --; } /*@cc_on node = this.createWrapper(node); @*/ return this._add(node); }; NodeSet.prototype.first = function() { if (this.only) return this.only; /*@cc_on if (this._first) return this._first.node; if (this.nodes.length > 1) this.sort(); var node = this.nodes[0]; return node ? node.node : undefined; @*/ if (this.nodes.length > 1) this.sort(); return this.nodes[0]; }; NodeSet.prototype.list = function() { if (this.only) return [this.only]; this.sort(); /*@cc_on var i, l, nodes, results; nodes = this.nodes; results = []; for (i = 0, l = nodes.length; i < l; i ++) { results.push(nodes[i].node); } return results; @*/ return this.nodes; }; NodeSet.prototype.string = function() { var node = this.only || this.first(); return node ? NodeUtil.to('string', node) : ''; }; NodeSet.prototype.bool = function() { return !! (this.length || this.only); }; NodeSet.prototype.number = function() { return + this.string(); }; NodeSet.prototype.iterator = function(reverse) { this.sort(); var nodeset = this; if (!reverse) { var count = 0; return function() { if (nodeset.only && count++ == 0) return nodeset.only; /*@cc_on @if(@_jscript) var wrapper = nodeset.nodes[count++]; if (wrapper) return wrapper.node; return undefined; @else @*/ return nodeset.nodes[count++]; /*@end @*/ }; } else { var count = 0; return function() { var index = nodeset.length - (count++) - 1; if (nodeset.only && index == 0) return nodeset.only; /*@cc_on @if(@_jscript) var wrapper = nodeset.nodes[index]; if (wrapper) return wrapper.node; return undefined; @else @*/ return nodeset.nodes[index]; /*@end @*/ }; } }; var install = function(win) { win = win || this; win.XPathExpression = function(expr) { if (!expr.length) { throw Error('no expression'); } var lexer = this.lexer = Lexer(expr); if (lexer.empty()) { throw Error('no expression'); } this.expr = BinaryExpr.parse(lexer); if (!lexer.empty()) { throw Error('bad token: ' + lexer.next()); } }; win.XPathExpression.prototype.evaluate = function(node, type) { return new XPathResult(this.expr.evaluate(new Ctx(node)), type); }; win.XPathResult = function (value, type) { if (type == 0) { switch (typeof value) { case 'object': type ++; // 4 case 'boolean': type ++; // 3 case 'string': type ++; // 2 case 'number': type ++; // 1 } } this.resultType = type; switch (type) { case 1: this.numberValue = value.isNodeSet ? value.number() : +value; return; case 2: this.stringValue = value.isNodeSet ? value.string() : '' + value; return; case 3: this.booleanValue = value.isNodeSet ? value.bool() : !! value; return; case 4: case 5: case 6: case 7: this.nodes = value.list(); this.snapshotLength = value.length; this.index = 0; this.invalidIteratorState = false; break; case 8: case 9: this.singleNodeValue = value.first(); return; } }; win.XPathResult.prototype.iterateNext = function() { return this.nodes[this.index++] }; win.XPathResult.prototype.snapshotItem = function(i) { return this.nodes[i] }; win.XPathResult.ANY_TYPE = 0; win.XPathResult.NUMBER_TYPE = 1; win.XPathResult.STRING_TYPE = 2; win.XPathResult.BOOLEAN_TYPE = 3; win.XPathResult.UNORDERED_NODE_ITERATOR_TYPE = 4; win.XPathResult.ORDERED_NODE_ITERATOR_TYPE = 5; win.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE = 6; win.XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7; win.XPathResult.ANY_UNORDERED_NODE_TYPE = 8; win.XPathResult.FIRST_ORDERED_NODE_TYPE = 9; win.document.createExpression = function(expr) { return new XPathExpression(expr, null); }; win.document.evaluate = function(expr, context, _, type) { return document.createExpression(expr, null).evaluate(context, type); }; }; var win; if (config.targetFrame) { var frame = document.getElementById(config.targetFrame); if (frame) win = frame.contentWindow; } install(win || window); })(); // Thanks for reading this source code. We love JavaScript. Swift-4.2.1/tests/_samples/charsets/iso-2022-jp/one.txt100644 0 0 7063 12000050367 17627 0ustar 0 0 ISO-2022-JPã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Š(特ã«é›»å­ãƒ¡ãƒ¼ãƒ«)ãªã©ã§ä½¿ã‚ã‚Œã‚‹æ—¥æœ¬ã®æ–‡å­—ç”¨ã®æ–‡å­—符å·åŒ–æ–¹å¼ã€‚ISO/IEC 2022ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスを利用ã—ã¦æ–‡å­—集åˆã‚’切り替ãˆã‚‹7ビットã®ã‚³ãƒ¼ãƒ‰ã§ã‚ã‚‹ã“ã¨ã‚’特徴ã¨ã™ã‚‹ (アナウンス機能ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスã¯çœç•¥ã•れる)。俗ã«ã€ŒJISコードã€ã¨å‘¼ã°ã‚Œã‚‹ã“ã¨ã‚‚ã‚る。 æ¦‚è¦ æ—¥æœ¬èªžè¡¨è¨˜ã¸ã®åˆ©ç”¨ãŒæƒ³å®šã•れã¦ã„る文字コードã§ã‚ã‚Šã€æ—¥æœ¬èªžã®åˆ©ç”¨ã•れるãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ãŠã„ã¦ã€æ—¥æœ¬ã®è¦æ ¼ã‚’応用ã—ãŸã‚‚ã®ã§ã‚る。ã¾ãŸæ–‡å­—集åˆã¨ã—ã¦ã¯ã€æ—¥æœ¬èªžã§ç”¨ã„られる漢字ã€ã²ã‚‰ãŒãªã€ã‚«ã‚¿ã‚«ãƒŠã¯ã‚‚ã¡ã‚ã‚“ã€ãƒ©ãƒ†ãƒ³æ–‡å­—ã€ã‚®ãƒªã‚·ã‚¢æ–‡å­—ã€ã‚­ãƒªãƒ«æ–‡å­—ãªã©ã‚‚å«ã‚“ã§ãŠã‚Šã€å­¦è¡“や産業ã®åˆ†é‡Žã§ã®åˆ©ç”¨ã‚‚考慮ãŸã‚‚ã®ã¨ãªã£ã¦ã„ã‚‹ã€‚è¦æ ¼åã«ã€ISOã®æ—¥æœ¬èªžã®è¨€èªžã‚³ãƒ¼ãƒ‰ã§ã‚ã‚‹jaã§ã¯ãªãã€å›½ãƒ»åœ°åŸŸåコードã®JPãŒç¤ºã•れã¦ã„るゆãˆã‚“ã§ã‚る。 文字集åˆã¨ã—ã¦JIS X 0201ã®C0集åˆï¼ˆåˆ¶å¾¡æ–‡å­—)ã€JIS X 0201ã®ãƒ©ãƒ†ãƒ³æ–‡å­—集åˆã€ISO 646ã®å›½éš›åŸºæº–版図形文字ã€JIS X 0208ã®1978年版(JIS C 6226-1978)ã¨1983å¹´ãŠã‚ˆã³1990年版ãŒåˆ©ç”¨ã§ãる。JIS X 0201ã®ç‰‡ä»®å文字集åˆã¯åˆ©ç”¨ã§ããªã„。1986年以é™ã€æ—¥æœ¬ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã§ç”¨ã„られã¦ããŸJUNETã‚³ãƒ¼ãƒ‰ã‚’ã€æ‘井純・Mark Crispin・Erik van der PoelãŒ1993å¹´ã«RFC化ã—ãŸã‚‚ã®(RFC 1468)。後ã«JIS X 0208:1997ã®é™„属書2ã¨ã—ã¦JISã«è¦å®šã•れãŸã€‚MIMEã«ãŠã‘る文字符å·åŒ–æ–¹å¼ã®è­˜åˆ¥ç”¨ã®åå‰ã¨ã—㦠IANA ã«ç™»éŒ²ã•れã¦ã„る。 ãªãŠã€ç¬¦å·åŒ–ã®ä»•様ã«ã¤ã„ã¦ã¯ISO/IEC 2022#ISO-2022-JPã‚‚å‚照。 ISO-2022-JPã¨éžæ¨™æº–的拡張使用 「JISコードã€ï¼ˆã¾ãŸã¯ã€ŒISO-2022-JPã€ï¼‰ã¨ã„ã†ã‚³ãƒ¼ãƒ‰åã®è¦å®šä¸‹ã§ã¯ã€ãã®ä»•様通りã®ä½¿ç”¨ãŒæ±‚ã‚られる。ã—ã‹ã—ã€Windows OS上ã§ã¯ã€å®Ÿéš›ã«ã¯CP932コード (Microsoftã«ã‚ˆã‚‹Shift JISã‚’æ‹¡å¼µã—ãŸäºœç¨®ã€‚ISO-2022-JPè¦å®šå¤–文字ãŒè¿½åŠ ã•れã¦ã„る。)ã«ã‚ˆã‚‹ç‹¬è‡ªæ‹¡å¼µï¼ˆã®æ–‡å­—)を断りãªã使ã†ã‚¢ãƒ—リケーションãŒå¤šã„。ã“ã®ä¾‹ã¨ã—ã¦Internet Explorerã‚„Outlook ExpressãŒã‚る。ã¾ãŸã€EmEditorã€ç§€ä¸¸ã‚¨ãƒ‡ã‚£ã‚¿ã‚„Thunderbirdã®ã‚ˆã†ãªMicrosoft社以外ã®Windowsアプリケーションã§ã‚‚åŒæ§˜ã®å ´åˆãŒã‚る。ã“ã®å ´åˆã€ISO-2022-JPã®ç¯„å›²å¤–ã®æ–‡å­—を使ã£ã¦ã—ã¾ã†ã¨ã€ç•°ãªã‚‹è£½å“é–“ã§ã¯æœªå®šç¾©ä¸æ˜Žæ–‡å­—ã¨ã—ã¦èªè­˜ã•れるã‹ã€ã‚‚ã—ãã¯æ–‡å­—化ã‘ã‚’èµ·ã“ã™åŽŸå› ã¨ãªã‚‹ã€‚ãã®ãŸã‚ã€Windows用ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã§ã‚ã£ã¦ã‚‚ç‹¬è‡ªæ‹¡å¼µã®æ–‡å­—を使用ã™ã‚‹ã¨è­¦å‘Šã‚’出ã—ãŸã‚Šã€ã‚ãˆã¦ä½¿ãˆãªã„よã†ã«åˆ¶é™ã—ã¦ã„ã‚‹ã‚‚ã®ã‚‚存在ã™ã‚‹ã€‚ã•らã«ã¯ISO-2022-JPã®ç¯„囲内ã§ã‚ã£ã¦ã‚‚CP932ã¯éžæ¨™æº–文字(FULLWIDTH TILDE等)をæŒã¤ã®ã§æ–‡å­—化ã‘ã®åŽŸå› ã«ãªã‚Šå¾—る。 ã¾ãŸã€ç¬¦å·åŒ–æ–¹å¼åã‚’ISO-2022-JPã¨ã—ã¦ã„ã‚‹ã®ã«ã€æ–‡å­—集åˆã¨ã—ã¦ã¯JIS X 0212 (ã„ã‚ゆる補助漢字) ã‚„JIS X 0201ã®ç‰‡ä»®åæ–‡å­—é›†åˆ (ã„ã‚ゆるåŠè§’カナ) をも符å·åŒ–ã—ã¦ã„る例ãŒã‚ã‚‹ãŒã€ISO-2022-JPã§ã¯ã“ã‚Œã‚‰ã®æ–‡å­—を許容ã—ã¦ã„ãªã„。ã“れらã®ç¬¦å·åŒ–ã¯ç‹¬è‡ªæ‹¡å¼µã®å®Ÿè£…ã§ã‚りã€ä¸­ã«ã¯ISO/IEC 2022ã®ä»•æ§˜ã«æº–æ‹ ã™ã‚‰ã—ã¦ã„ãªã„ã‚‚ã®ã‚‚ã‚ã‚‹[2]。従ã£ã¦å—ä¿¡å´ã®é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆãŒã“れらã®ç‹¬è‡ªæ‹¡å¼µã«å¯¾å¿œã—ã¦ã„ãªã„å ´åˆã€ãã®æ–‡å­—ã‚ã‚‹ã„ã¯ãã®æ–‡å­—ã‚’å«ã‚€è¡Œã€æ™‚ã«ã¯ãƒ†ã‚­ã‚¹ãƒˆå…¨ä½“ãŒæ–‡å­—化ã‘ã™ã‚‹ã“ã¨ãŒã‚る。 Swift-4.2.1/tests/_samples/charsets/iso-8859-1/one.txt100644 0 0 5606 12000050367 17407 0ustar 0 0 Op mat eraus hinnen beschte, rou zënne schaddreg ké. Ké sin Eisen Kaffi prächteg, den haut esou Fielse wa, Well zielen d'Welt am dir. Aus grousse rëschten d'Stroos do, as dat Kléder gewëss d'Kàchen. Schied gehéiert d'Vioule net hu, rou ke zënter Säiten d'Hierz. Ze eise Fletschen mat, gei as gréng d'Lëtzebuerger. Wäit räich no mat. Säiten d'Liewen aus en. Un gëtt bléit lossen wee, da wéi alle weisen Kolrettchen. Et deser d'Pan d'Kirmes vun, en wuel Benn rëschten méi. En get drem ménger beschte, da wär Stad welle. Nun Dach d'Pied do, mä gét ruffen gehéiert. Ze onser ugedon fir, d'Liewen Plett'len ech no, si Räis wielen bereet wat. Iwer spilt fir jo. An hin däischter Margréitchen, eng ke Frot brommt, vu den Räis néierens. Da hir Hunn Frot nozegon, rout Fläiß Himmel zum si, net gutt Kaffi Gesträich fu. Vill lait Gaart sou wa, Land Mamm Schuebersonndeg rei do. Gei geet Minutt en, gei d'Leit beschte Kolrettchen et, Mamm fergiess un hun. Et gutt Heck kommen oft, Lann rëscht rei um, Hunn rëscht schéinste ke der. En lait zielen schnéiwäiss hir, fu rou botze éiweg Minutt, rem fest gudden schaddreg en. Noper bereet Margréitchen mat op, dem denkt d'Leit d'Vioule no, oft ké Himmel Hämmel. En denkt blénken Fréijor net, Gart Schiet d'Natur no wou. No hin Ierd Frot d'Kirmes. Hire aremt un rou, ké den éiweg wielen Milliounen. Mir si Hunn Blénkeg. Ké get ston derfir d'Kàchen. Haut d'Pan fu ons, dé frou löschteg d'Meereische rei. Sou op wuel Léift. Stret schlon grousse gin hu. Mä denkt d'Leit hinnen net, ké gét haut fort rëscht. Koum d'Pan hannendrun ass ké, ké den brét Kaffi geplot. Schéi Hären d'Pied fu gét, do d'Mier néierens bei. Rëm päift Hämmel am, wee Engel beschéngt mä. Brommt klinzecht der ke, wa rout jeitzt dén. Get Zalot d'Vioule däischter da, jo fir Bänk päift duerch, bei d'Beem schéinen Plett'len jo. Den haut Faarwen ze, eng en Biereg Kirmesdag, um sin alles Faarwen d'Vioule. Eng Hunn Schied et, wat wa Frot fest gebotzt. Bei jo bleiwe ruffen Klarinett. Un Feld klinzecht gét, rifft Margréitchen rem ke. Mir dé Noper duurch gewëss, ston sech kille sin en. Gei Stret d'Wise um, Haus Gart wee as. Monn ménger an blo, wat da Gart gefällt Hämmelsbrot. Brommt geplot och ze, dat wa Räis Well Kaffi. Do get spilt prächteg, as wär kille bleiwe gewalteg. Onser frësch Margréitchen rem ke, blo en huet ugedon. Onser Hemecht wär de, hu eraus d'Sonn dat, eise deser hannendrun da och. As durch Himmel hun, no fest iw'rem schéinste mir, Hunn séngt Hierz ke zum. Séngt iw'rem d'Natur zum an. Ke wär gutt Grénge. Kënnt gudden prächteg mä rei. Dé dir Blénkeg Klarinett Kolrettchen, da fort muerges d'Kanner wou, main Feld ruffen vu wéi. Da gin esou Zalot gewalteg, gét vill Hemecht blénken dé. Haut gréng nun et, nei vu Bass gréng d'Gaassen. Fest d'Beem uechter si gin. Oft vu sinn wellen kréien. Et ass lait Zalot schéinen.Swift-4.2.1/tests/_samples/charsets/utf-8/one.txt100644 0 0 3733 12000050367 17006 0ustar 0 0 Код одно гринÑпана руководишь на. Его вы Ð·Ð½Ð°Ð½Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ðµ. Ты две начать одиночку, Ñказать оÑнователь удовольÑтвием но миф. Бы какие ÑиÑтема тем. ПолноÑтью иÑпользует три мы, человек клоунов те наÑ, бы давать творчеÑкую ÑзотеричеÑÐºÐ°Ñ ÑˆÐµÑ„. Мог не помнить никакого ÑÑкономленного, две либо какие пишите бы. Должен компанию кто те, Ñтот заключалаÑÑŒ проектировщик не ты. Глупые периоды ты длÑ. Вам который хороший он. Те любых ÐºÑ€ÐµÐ¼Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ†ÐµÐ½Ñ‚Ñ€Ð¸Ñ€ÑƒÑŽÑ‚ÑÑ Ð¼Ð¾Ð³, Ñобирать принадлежите без вы. ДжоÑла меньше хорошего вы миф, за тем году разработки. Даже управлÑющим руководители был не. Три коде выпуÑкать заботитьÑÑ Ð½Ñƒ. То его ÑиÑтема удовольÑтвием безоÑтановочно, или ты главной процеÑÑорах. Мы без джоÑл Ð·Ð½Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚, Ñтатьи оÑтальные мы ещё. Ðих руÑÑком каÑаетÑÑ Ð¿Ð¾Ñкольку по, образование должником ÑиÑтематизированный ну мои. Прийти кандидата универÑитет но наÑ, Ð´Ð»Ñ Ð±Ñ‹ должны никакого, биг многие причин Ð¸Ð½Ñ‚ÐµÑ€Ð²ÑŒÑŽÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°. Тем до плиту почему. Вот учёт такие одного бы, об биг разным внешних промежуток. Ð’Ð°Ñ Ð´Ð¾ какому возможноÑтей безответÑтвенный, были погодите бы его, по них глупые долгий количеÑтва. Swift-4.2.1/tests/_samples/charsets/utf-8/three.txt100644 0 0 30711 12000050367 17350 0ustar 0 0 Αν ήδη διάβασε γλιτώσει μεταγλωτίσει, αυτήν θυμάμαι μου μα. Την κατάσταση χÏησιμοποίησέ να! Τα διαφοÏά φαινόμενο διολισθήσεις πες, υψηλότεÏη Ï€Ïοκαλείς πεÏισσότεÏες όχι κι. Με ελέγχου γίνεται σας, μικÏής δημιουÏγοÏν τη του. Τις τα γÏάψει εικόνες απαÏάδεκτη? Îα ότι Ï€Ïώτοι απαÏαίτητο. Άμεση πετάνε κακόκεφος τον ÏŽÏ‚, να χώÏου πιθανότητες του. Το μέχÏι οÏίστε λιγότεÏους σας. Πω ναί φυσικά εικόνες. Μου οι κώδικα αποκλειστικοÏÏ‚, λες το μάλλον συνεχώς. Îέου σημεία απίστευτα σας μα. ΧÏόνου μεταγλωτιστής σε νέα, τη τις πιάνει μποÏοÏσες Ï€ÏογÏαμματιστές. Των κάνε βγαίνει εντυπωσιακό τα? ΚÏατάει τεσσαÏών δυστυχώς της κι, ήδη υψηλότεÏη εξακολουθεί τα? ÎÏα πετάνε μποÏοÏσε λιγότεÏους αν, τα απαÏάδεκτη συγχωνευτεί Ïοή. Τη έγÏαψες συνηθίζουν σαν. Όλα με υλικό στήλες χειÏότεÏα. Ανώδυνη δουλέψει επί ως, αν διαδίκτυο εσωτεÏικών παÏάγοντες από. ΚεντÏικό επιτυχία πες το. Πω ναι λέει τελειώσει, έξι ως έÏγων τελειώσει. Με αÏχεία βουτήξουν ανταγωνιστής ÏŽÏα, Ï€Î¿Î»Ï Î³Ïαφικά σελίδων τα στη. ÎŒÏο οέλεγχος δημιουÏγοÏν δε, ας θέλεις ελέγχου συντακτικό ÏŒÏο! Της θυμάμαι επιδιόÏθωση τα. Για μποÏοÏσε πεÏισσότεÏο αν, μέγιστη σημαίνει αποφάσισε τα του, άτομο αποτελέσει τι στα. Τι στην αφήσεις διοίκηση στη. Τα εσφαλμένη δημιουÏγια επιχείÏιση έξι! Βήμα μαγικά εκτελέσει ανά τη. Όλη αφήσεις συνεχώς εμποÏικά αν, το λες κόλπα επιτυχία. Ότι οι ζώνη κειμένων. ÎŒÏο κι Ïωτάει γÏαμμής πελάτες, τελειώσει διολισθήσεις καθυστεÏοÏσε αν εγώ? Τι πετοÏν διοίκηση Ï€Ïοβλήματα ήδη. Τη γλιτώσει Î±Ï€Î¿Î¸Î·ÎºÎµÏ…Ï„Î¹ÎºÎ¿Ï Î¼Î¹Î±. Πω έξι δημιουÏγια πιθανότητες, ως πέντε ελέγχους εκτελείται λες. Πως εÏωτήσεις διοικητικό συγκεντÏωμένοι οι, ας συνεχώς διοικητικό αποστηθίσει σαν. Δε Ï€Ïώτες συνεχώς διολισθήσεις έχω, από τι κανένας βουτήξουν, γειτονιάς Ï€Ïοσεκτικά ανταγωνιστής κι σαν. ΔημιουÏγια συνηθίζουν κλπ τι? Όχι ποσοστό διακοπής κι. Κλπ φακέλους δεδομένη εξοÏγιστικά θα? Υποψήφιο καθοÏίζουν με όλη, στα πήÏε Ï€Ïοσοχή εταιÏείες πω, ÏŽÏ‚ τον συνάδελφος διοικητικό δημιουÏγήσεις! ΔοÏλευε επιτίθενται σας θα, με ένας παÏαγωγικής ένα, να ναι σημεία μέγιστη απαÏάδεκτη? Σας τεσσαÏών συνεντεÏξης τη, αÏπάζεις σίγουÏος μη για', επί τοπικές εντολές ακοÏσει θα? Ως δυστυχής μεταγλωτιστής όλη, να την είχαν σφάλμα απαÏαίτητο! Μην ÏŽÏ‚ άτομο διοÏθώσει χÏησιμοποιοÏνταν. Δεν τα κόλπα πετάξαμε, μη που άγχος Ï…ÏŒÏκη άμεση, Î±Ï†Î¿Ï Î´Ï…ÏƒÏ„Ï…Ï‡ÏŽÏ‚ διακόψουμε ÏŒÏο αν! Όλη μαγικά πετάνε επιδιοÏθώσεις δε, Ïοή φυσικά αποτελέσει πω. ΆπειÏα παÏαπάνω φαινόμενο πω ÏŽÏα, σαν πόÏτες κÏατήσουν συνηθίζουν ως. Κι ÏŽÏα Ï„Ïέξει είχαμε εφαÏμογή. Απλό σχεδιαστής μεταγλωτιστής ας επί, τις τα όταν έγÏαψες γÏαμμής? Όλα κάνεις συνάδελφος εÏγαζόμενοι θα, χαÏÏ„Î¹Î¿Ï Ï‡Î±Î¼Î·Î»ÏŒÏ‚ τα Ïοή. Ως ναι ÏŒÏοφο έÏθει, μην πελάτες αποφάσισε μεταφÏαστής με, να βιαστικά εκδόσεις αναζήτησης λες. Των φταίει εκθέσεις Ï€Ïοσπαθήσεις οι, σπίτι αποστηθίσει ας λες? ÎÏ‚ που υπηÏεσία απαÏαίτητο δημιουÏγείς. Μη άÏα χαÏά καθώς νÏχτας, πω ματ μπουν είχαν. Άμεση δημιουÏγείς ÏŽÏ‚ Ïοή, γÏάψει γÏαμμής σίγουÏος στα τι! Αν Î±Ï†Î¿Ï Ï€Ïώτοι εÏγαζόμενων ναί. Άμεση διοÏθώσεις με δÏο? Έχουν παÏάδειγμα των θα, μου έÏθει θυμάμαι πεÏισσότεÏο το. Ότι θα Î±Ï†Î¿Ï Ï‡Ïειάζονται πεÏισσότεÏες. Σαν συνεχώς πεÏίπου οι. ÎÏ‚ Ï€Ïώτης πετάξαμε λες, ÏŒÏο κι Ï€Ïώτες ζητήσεις δυστυχής. Ανά χÏόνου διακοπή επιχειÏηματίες ας, ÏŽÏ‚ μόλις άτομο χειÏότεÏα ÏŒÏο, κÏατάει σχεδιαστής Ï€Ïοσπαθήσεις νέο το. Πουλάς Ï€Ïοσθέσει όλη πω, Ï„Ïπου χαÏακτηÏιστικό εγώ σε, πω πιο δοÏλευε αναζήτησης? ΑναφοÏά δίνοντας σαν μη, μάθε δεδομένη εσωτεÏικών με ναι, αναφέÏονται πεÏιβάλλοντος ÏŽÏα αν. Και λέει απόλαυσε τα, που το ÏŒÏοφο Ï€ÏοσπαθοÏν? Πάντα χÏόνου χÏήματα ναι το, σαν σωστά θυμάμαι σκεφτείς τα. Μα αποτελέσει ανεπιθÏμητη την, πιο το τέτοιο ατόμου, τη των Ï„Ïόπο εÏγαλείων επιδιόÏθωσης. ΠεÏιβάλλον παÏαγωγικής σου κι, κλπ οι Ï„Ïπου κακόκεφους αποστηθίσει, δε των πλέον Ï„Ïόποι. Πιθανότητες χαÏακτηÏιστικών σας κι, γÏαφικά δημιουÏγήσεις μια οι, πω πολλοί εξαÏτάται Ï€Ïοσεκτικά εδώ. Σταματάς παÏάγοντες για' ÏŽÏ‚, στις Ïωτάει το ναι! ΚαÏέκλα ζητήσεις συνδυασμοÏÏ‚ τη ήδη! Για μαγικά συνεχώς ακοÏσει το. Σταματάς Ï€Ïοϊόντα βουτήξουν ÏŽÏ‚ Ïοή. Είχαν Ï€Ïώτες οι ναι, μα λες αποστηθίσει ανακαλÏπτεις. ÎŒÏοφο άλγεβÏα παÏαπάνω εδώ τη, Ï€Ïόσληψη λαμβάνουν καταλάθος ήδη ας? Ως και εισαγωγή κÏατήσουν, ένας κακόκεφους κι μας, όχι κώδικάς παίξουν πω. Πω νέα κÏατάει εκφÏάσουν, τότε τελικών τη όχι, ας της Ï„Ïέξει αλλάζοντας αποκλειστικοÏÏ‚. Ένας βιβλίο σε άÏα, ναι ως γÏάψει ταξινομεί διοÏθώσεις! Εδώ να γεγονός συγγÏαφείς, ÏŽÏ‚ ήδη διακόψουμε επιχειÏηματίες? Ότι πακέτων εσφαλμένη κι, θα ÏŒÏο κόλπα παÏαγωγικής? Αν έχω κεντÏικό υψηλότεÏη, κι δεν ίδιο πετάνε παÏατηÏοÏμενη! Που λοιπόν σημαντικό μα, Ï€Ïοκαλείς χειÏοκÏοτήματα ως όλα, μα επί κόλπα άγχος γÏαμμές! Δε σου κάνεις βουτήξουν, μη έÏγων επενδυτής χÏησιμοποίησέ στα, ως του Ï€Ïώτες διάσημα σημαντικό. Βιβλίο τεÏάστιο Ï€ÏοκÏπτουν σαν το, σαν Ï„Ïόπο επιδιόÏθωση ας. Είχαν Ï€Ïοσοχή Ï€Ïοσπάθεια κι ματ, εδώ ως έτσι σελίδων συζήτηση. Και στην βγαίνει εσφαλμένη με, δυστυχής παÏάδειγμα δε μας, από σε Ï…ÏŒÏκη επιδιόÏθωσης. Îέα πω νέου πιθανό, στήλες συγγÏαφείς μπαίνοντας μα για', το Ïωτήσει κακόκεφους της? Μου σε αÏέσει συγγÏαφής συγχωνευτεί, μη μου Ï…ÏŒÏκη ξέχασε διακοπής! ÎÏ‚ επί αποφάσισε αποκλειστικοÏÏ‚ χÏησιμοποιώντας, χÏήματα σελίδων ταξινομεί ναι με. Μη ανά γÏαμμή απόλαυσε, πω ναι μάτσο διασφαλίζεται. Τη έξι μόλις εÏγάστηκε δημιουÏγοÏν, έκδοση αναφοÏά δυσκολότεÏο οι νέο. Σας ως μποÏοÏσε παÏάδειγμα, αν ότι δοÏλευε μποÏοÏσε αποκλειστικοÏÏ‚, πιο λέει βουτήξουν διοÏθώσει ως. Έχω τελευταία κακόκεφους ας, όσο εÏγαζόμενων δημιουÏγήσεις τα. Του αν δουλέψει μποÏοÏσε, πετοÏν χαμηλός εδώ ας? ΚÏκλο Ï„Ïπους με που, δεν σε έχουν συνεχώς χειÏότεÏα, τις τι απαÏάδεκτη συνηθίζουν? Θα μην τους αυτήν, τη ένα πήÏε πακέτων, κι Ï€ÏοκÏπτουν πεÏιβάλλον πως. Μα για δουλέψει απόλαυσε εφαμοÏγής, ÏŽÏ‚ εδώ σημαίνει μποÏοÏσες, άμεση ακοÏσει Ï€Ïοσοχή τη εδώ? Στα δώσε αθόÏυβες λιγότεÏους οι, δε αναγκάζονται αποκλειστικοÏÏ‚ όλα! Ας μπουν διοικητικό μια, πάντα ελέγχου διοÏθώσεις ÏŽÏ‚ τον. Ότι πήÏε κανόνα μα. Που άτομα κάνεις δημιουÏγίες τα, οι μας Î±Ï†Î¿Ï ÎºÏŒÎ»Ï€Î± Ï€ÏογÏαμματιστής, Î±Ï†Î¿Ï Ï‰Ïαίο Ï€ÏοκÏπτουν στα ως. Θέμα χÏησιμοποιήσει αν όλα, του τα άλγεβÏα σελίδων. Τα ότι ανώδυνη δυστυχώς συνδυασμοÏÏ‚, μας οι πάντα γνωÏίζουμε ανταγωνιστής, όχι τα δοκιμάσεις σχεδιαστής! Στην συνεντεÏξης επιδιόÏθωση πιο τα, μα από πουλάς πεÏιβάλλον παÏαγωγικής. Έχουν μεταγλωτίσει σε σας, σε πάντα Ï€Ïώτης μειώσει των, γÏάψει Ïουτίνα δυσκολότεÏο ήδη μα? Ταξινομεί διοÏθώσεις να μας. Θα της Ï€ÏοσπαθοÏν πεÏιεχόμενα, δε έχω τοπικές στέλνοντάς. Ανά δε αλφα άμεση, κάποιο Ïωτάει γνωÏίζουμε πω στη, φÏάση μαγικά συνέχεια δε δÏο! Αν είχαμε μειώσει Ïοή, μας μετÏάει καθυστεÏοÏσε επιδιοÏθώσεις μη. Χάος Ï…ÏŒÏκη κεντÏικό έχω σε, ανά πεÏίπου αναγκάζονται πω. Όσο επιστÏέφουν χÏονοδιαγÏάμματα μη. Πως ωÏαίο κακόκεφος διαχειÏιστής ως, τις να διακοπής αναζήτησης. Κάποιο ποσοστό ταξινομεί επί τη? Μάθε άμεση αλλάζοντας δÏο με, μου νέου πάντα να. Πω του δυστυχώς πιθανότητες. Κι Ïωτάει υψηλότεÏη δημιουÏγια ότι, πω εισαγωγή τελευταία απομόνωση ναι. Των ζητήσεις γνωÏίζουμε ÏŽÏ‚? Για' μη παÏαδοτέου αναφέÏονται! Ύψος παÏαγωγικά Ïοή ως, φυσικά διάβασε εικόνες όσο σε? Δεν Ï…ÏŒÏκη διοÏθώσεις επεξεÏγασία θα, ως μέση σÏστημα χÏησιμοποιήσει τις.Swift-4.2.1/tests/_samples/charsets/utf-8/two.txt100644 0 0 3356 12000050367 17037 0ustar 0 0 रखति आवशà¥à¤¯à¤•त पà¥à¤°à¥‡à¤°à¤¨à¤¾ मà¥à¤–à¥à¤¯à¤¤à¤¹ हिंदी किà¤à¤²à¥‹à¤— असकà¥à¤·à¤® कारà¥à¤¯à¤²à¤¯ करते विवरण किके मानसिक दिनांक पà¥à¤°à¥à¤µ संसाध à¤à¤µà¤®à¥ कà¥à¤¶à¤²à¤¤à¤¾ अमितकà¥à¤®à¤¾à¤° पà¥à¤°à¥‹à¤¤à¥à¤¸à¤¾à¤¹à¤¿à¤¤ जनित देखने उदेशीत विकसित बलवान बà¥à¤°à¥Œà¤¶à¤° किà¤à¤²à¥‹à¤— विशà¥à¤²à¥‡à¤·à¤£ लोगो कैसे जागरà¥à¤• पà¥à¤°à¤µà¥à¤°à¥à¤¤à¤¿ पà¥à¤°à¥‹à¤¤à¥à¤¸à¤¾à¤¹à¤¿à¤¤ सदसà¥à¤¯ आवशà¥à¤¯à¤•त पà¥à¤°à¤¸à¤¾à¤°à¤¨ उपलबà¥à¤§à¤¤à¤¾ अथवा हिंदी जनित दरà¥à¤¶à¤¾à¤¤à¤¾ यनà¥à¤¤à¥à¤°à¤¾à¤²à¤¯ बलवान अतित सहयोग शà¥à¤°à¥à¤†à¤¤ सभीकà¥à¤› माहितीवानीजà¥à¤¯ लिये खरिदे है।अभी à¤à¤•तà¥à¤°à¤¿à¤¤ समà¥à¤ªà¤°à¥à¤• रिती मà¥à¤¶à¥à¤•िल पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤• भेदनकà¥à¤·à¤®à¤¤à¤¾ विशà¥à¤µ उनà¥à¤¹à¥‡ गटको दà¥à¤µà¤¾à¤°à¤¾ तकरीबन विशà¥à¤µ दà¥à¤µà¤¾à¤°à¤¾ वà¥à¤¯à¤¾à¤–à¥à¤¯à¤¾ सके। आजपर वातावरण वà¥à¤¯à¤¾à¤–à¥à¤¯à¤¾à¤¨ पहोच। हमारी कीसे पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤• विचारशिलता पà¥à¤°à¥à¤µ करती कमà¥à¤ªà¥à¤¯à¥à¤Ÿà¤° भेदनकà¥à¤·à¤®à¤¤à¤¾ लिये बलवान औरà¥à¥ªà¥«à¥¦ यायेका वारà¥à¤¤à¤¾à¤²à¤¾à¤ª सà¥à¤šà¤¨à¤¾ भारत शà¥à¤°à¥à¤†à¤¤ लाभानà¥à¤µà¤¿à¤¤ पढाठसंसà¥à¤¥à¤¾ वरà¥à¤£à¤¿à¤¤ मारà¥à¤—दरà¥à¤¶à¤¨ चà¥à¤¨à¤¨à¥‡Swift-4.2.1/tests/_samples/files/data.txt100644 0 0 6 12000050367 15367 0ustar 0 0 Swift-4.2.1/tests/_samples/files/textfile.zip100644 0 0 312 12000050367 16325 0ustar 0 0 PK ȺV8ŽN"°.. textfile.txtUT w¾¾Gw¾¾GUxõõThis is part of a Swift Mailer v4 smoke test. PK ȺV8ŽN"°.. ¤textfile.txtUTw¾¾GUxPKGmSwift-4.2.1/tests/acceptance.conf.php100644 0 0 2076 12000050367 14624 0ustar 0 0 skipUnless( SWIFT_TMP_DIR, 'Cannot run test without a writable directory to use (' . 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)' ); } public function setUp() { $this->_tmpDir = SWIFT_TMP_DIR; $this->_testFile = $this->_tmpDir . '/swift-test-file' . __CLASS__; file_put_contents($this->_testFile, 'abcdefghijklm'); } public function tearDown() { unlink($this->_testFile); } public function testFileDataCanBeRead() { $file = $this->_createFileStream($this->_testFile); $str = ''; while (false !== $bytes = $file->read(8192)) { $str .= $bytes; } $this->assertEqual('abcdefghijklm', $str); } public function testFileDataCanBeReadSequentially() { $file = $this->_createFileStream($this->_testFile); $this->assertEqual('abcde', $file->read(5)); $this->assertEqual('fghijklm', $file->read(8)); $this->assertFalse($file->read(1)); } public function testFilenameIsReturned() { $file = $this->_createFileStream($this->_testFile); $this->assertEqual($this->_testFile, $file->getPath()); } public function testFileCanBeWrittenTo() { $file = $this->_createFileStream( $this->_testFile, true ); $file->write('foobar'); $this->assertEqual('foobar', $file->read(8192)); } public function testReadingFromThenWritingToFile() { $file = $this->_createFileStream( $this->_testFile, true ); $file->write('foobar'); $this->assertEqual('foobar', $file->read(8192)); $file->write('zipbutton'); $this->assertEqual('zipbutton', $file->read(8192)); } public function testWritingToFileWithCanonicalization() { $file = $this->_createFileStream( $this->_testFile, true ); $file->addFilter($this->_createFilter(array("\r\n", "\r"), "\n"), 'allToLF'); $file->write("foo\r\nbar\r"); $file->write("\nzip\r\ntest\r"); $file->flushBuffers(); $this->assertEqual("foo\nbar\nzip\ntest\n", file_get_contents($this->_testFile)); } public function testBindingOtherStreamsMirrorsWriteOperations() { $file = $this->_createFileStream( $this->_testFile, true ); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') -> one($is2)->write('y') ); $file->bind($is1); $file->bind($is2); $file->write('x'); $file->write('y'); } public function testBindingOtherStreamsMirrorsFlushOperations() { $file = $this->_createFileStream( $this->_testFile, true ); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->flushBuffers() -> one($is2)->flushBuffers() ); $file->bind($is1); $file->bind($is2); $file->flushBuffers(); } public function testUnbindingStreamPreventsFurtherWrites() { $file = $this->_createFileStream( $this->_testFile, true ); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') ); $file->bind($is1); $file->bind($is2); $file->write('x'); $file->unbind($is2); $file->write('y'); } // -- Creation methods private function _createFilter($search, $replace) { return new Swift_StreamFilters_StringReplacementFilter($search, $replace); } private function _createMockInputStream() { return $this->_mock('Swift_InputByteStream'); } private function _createFileStream($file, $writable = false) { return new Swift_ByteStream_FileByteStream($file, $writable); } } ././@LongLink100644 0 0 151 12000050367 10341 Lustar 0 0 Swift-4.2.1/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.phpSwift-4.2.1/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest100644 0 0 14724 12000050367 31130 0ustar 0 0 _factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); } public function testCreatingUtf8Reader() { foreach (array('utf8', 'utf-8', 'UTF-8', 'UTF8') as $utf8) { $reader = $this->_factory->getReaderFor($utf8); $this->assertIsA($reader, $this->_prefix . 'Utf8Reader'); } } public function testCreatingIso8859XReaders() { $charsets = array(); foreach (range(1, 16) as $number) { foreach (array('iso', 'iec') as $body) { $charsets[] = $body . '-8859-' . $number; $charsets[] = $body . '8859-' . $number; $charsets[] = strtoupper($body) . '-8859-' . $number; $charsets[] = strtoupper($body) . '8859-' . $number; } } foreach ($charsets as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingWindows125XReaders() { $charsets = array(); foreach (range(0, 8) as $number) { $charsets[] = 'windows-125' . $number; $charsets[] = 'windows125' . $number; $charsets[] = 'WINDOWS-125' . $number; $charsets[] = 'WINDOWS125' . $number; } foreach ($charsets as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingCodePageReaders() { $charsets = array(); foreach (range(0, 8) as $number) { $charsets[] = 'cp-125' . $number; $charsets[] = 'cp125' . $number; $charsets[] = 'CP-125' . $number; $charsets[] = 'CP125' . $number; } foreach (array(437, 737, 850, 855, 857, 858, 860, 861, 863, 865, 866, 869) as $number) { $charsets[] = 'cp-' . $number; $charsets[] = 'cp' . $number; $charsets[] = 'CP-' . $number; $charsets[] = 'CP' . $number; } foreach ($charsets as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingAnsiReader() { foreach (array('ansi', 'ANSI') as $ansi) { $reader = $this->_factory->getReaderFor($ansi); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingMacintoshReader() { foreach (array('macintosh', 'MACINTOSH') as $mac) { $reader = $this->_factory->getReaderFor($mac); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingKOIReaders() { $charsets = array(); foreach (array('7', '8-r', '8-u', '8u', '8r') as $end) { $charsets[] = 'koi-' . $end; $charsets[] = 'koi' . $end; $charsets[] = 'KOI-' . $end; $charsets[] = 'KOI' . $end; } foreach ($charsets as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingIsciiReaders() { foreach (array('iscii', 'ISCII', 'viscii', 'VISCII') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingMIKReader() { foreach (array('mik', 'MIK') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingCorkReader() { foreach (array('cork', 'CORK', 't1', 'T1') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(1, $reader->getInitialByteSize()); } } public function testCreatingUcs2Reader() { foreach (array('ucs-2', 'UCS-2', 'ucs2', 'UCS2') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(2, $reader->getInitialByteSize()); } } public function testCreatingUtf16Reader() { foreach (array('utf-16', 'UTF-16', 'utf16', 'UTF16') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(2, $reader->getInitialByteSize()); } } public function testCreatingUcs4Reader() { foreach (array('ucs-4', 'UCS-4', 'ucs4', 'UCS4') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(4, $reader->getInitialByteSize()); } } public function testCreatingUtf32Reader() { foreach (array('utf-32', 'UTF-32', 'utf32', 'UTF32') as $charset) { $reader = $this->_factory->getReaderFor($charset); $this->assertIsA($reader, $this->_prefix . 'GenericFixedWidthReader'); $this->assertEqual(4, $reader->getInitialByteSize()); } } } Swift-4.2.1/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php100644 0 0 1117 12000050367 23517 0ustar 0 0 listItems() as $itemName) { try { $di->lookup($itemName); } catch (Swift_DependencyException $e) { $this->fail($e->getMessage()); } } } } Swift-4.2.1/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php100644 0 0 455 12000050367 22053 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../_samples/charsets'); $this->_encoder = new Swift_Encoder_Base64Encoder(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $encodedText = $this->_encoder->encodeString($text); $this->assertEqual( base64_decode($encodedText), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } } Swift-4.2.1/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php100644 0 0 3671 12000050367 23044 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../_samples/charsets'); $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $encoding = $encodingDir; $charStream = new Swift_CharacterStream_ArrayCharacterStream( $this->_factory, $encoding); $encoder = new Swift_Encoder_QpEncoder($charStream); $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $encodedText = $encoder->encodeString($text); $this->assertEqual( quoted_printable_decode($encodedText), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } } Swift-4.2.1/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php100644 0 0 3621 12000050367 23501 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../_samples/charsets'); $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $encoding = $encodingDir; $charStream = new Swift_CharacterStream_ArrayCharacterStream( $this->_factory, $encoding); $encoder = new Swift_Encoder_Rfc2231Encoder($charStream); $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $encodedText = $encoder->encodeString($text); $this->assertEqual( urldecode(implode('', explode("\r\n", $encodedText))), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } } Swift-4.2.1/tests/acceptance/Swift/EncodingAcceptanceTest.php100644 0 0 1627 12000050367 21332 0ustar 0 0 assertEqual('7bit', $encoder->getName()); } public function testGet8BitEncodingReturns8BitEncoder() { $encoder = Swift_Encoding::get8BitEncoding(); $this->assertEqual('8bit', $encoder->getName()); } public function testGetQpEncodingReturnsQpEncoder() { $encoder = Swift_Encoding::getQpEncoding(); $this->assertEqual('quoted-printable', $encoder->getName()); } public function testGetBase64EncodingReturnsBase64Encoder() { $encoder = Swift_Encoding::getBase64Encoding(); $this->assertEqual('base64', $encoder->getName()); } } Swift-4.2.1/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php100644 0 0 13636 12000050367 23756 0ustar 0 0 _cache = new Swift_KeyCache_ArrayKeyCache( new Swift_KeyCache_SimpleKeyCacheInputStream() ); } public function testStringDataCanBeSetAndFetched() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeOverwritten() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('whatever', $this->_cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeAppended() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testing', $this->_cache->getString($this->_key1, 'foo')); } public function testHasKeyReturnValue() { $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); } public function testNsKeyIsWellPartitioned() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $this->_cache->getString($this->_key2, 'foo')); } public function testItemKeyIsWellPartitioned() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $this->_cache->getString($this->_key1, 'bar')); } public function testByteStreamCanBeImported() { $os = new Swift_ByteStream_ArrayByteStream(); $os->write('abcdef'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE ); $this->assertEqual('abcdef', $this->_cache->getString($this->_key1, 'foo')); } public function testByteStreamCanBeAppended() { $os1 = new Swift_ByteStream_ArrayByteStream(); $os1->write('abcdef'); $os2 = new Swift_ByteStream_ArrayByteStream(); $os2->write('xyzuvw'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND ); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo')); } public function testByteStreamAndStringCanBeAppended() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND ); $os = new Swift_ByteStream_ArrayByteStream(); $os->write('abcdef'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testabcdef', $this->_cache->getString($this->_key1, 'foo')); } public function testDataCanBeExportedToByteStream() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $is = new Swift_ByteStream_ArrayByteStream(); $this->_cache->exportToByteStream($this->_key1, 'foo', $is); $string = ''; while (false !== $bytes = $is->read(8192)) { $string .= $bytes; } $this->assertEqual('test', $string); } public function testKeyCanBeCleared() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); $this->_cache->clearKey($this->_key1, 'foo'); $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); } public function testNsKeyCanBeCleared() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); $this->assertTrue($this->_cache->hasKey($this->_key1, 'bar')); $this->_cache->clearAll($this->_key1); $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); $this->assertFalse($this->_cache->hasKey($this->_key1, 'bar')); } public function testKeyCacheInputStream() { $is = $this->_cache->getInputByteStream($this->_key1, 'foo'); $is->write('abc'); $is->write('xyz'); $this->assertEqual('abcxyz', $this->_cache->getString($this->_key1, 'foo')); } } Swift-4.2.1/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php100644 0 0 14311 12000050367 23561 0ustar 0 0 skipUnless( SWIFT_TMP_DIR, 'Cannot run test without a writable directory to use (' . 'define SWIFT_TMP_DIR in tests/config.php if you wish to run this test)' ); } public function setUp() { $this->_key1 = uniqid(microtime(true), true); $this->_key2 = uniqid(microtime(true), true); $this->_cache = new Swift_KeyCache_DiskKeyCache( new Swift_KeyCache_SimpleKeyCacheInputStream(), SWIFT_TMP_DIR ); } public function testStringDataCanBeSetAndFetched() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeOverwritten() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('whatever', $this->_cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeAppended() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testing', $this->_cache->getString($this->_key1, 'foo')); } public function testHasKeyReturnValue() { $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); } public function testNsKeyIsWellPartitioned() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $this->_cache->getString($this->_key2, 'foo')); } public function testItemKeyIsWellPartitioned() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $this->_cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $this->_cache->getString($this->_key1, 'bar')); } public function testByteStreamCanBeImported() { $os = new Swift_ByteStream_ArrayByteStream(); $os->write('abcdef'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE ); $this->assertEqual('abcdef', $this->_cache->getString($this->_key1, 'foo')); } public function testByteStreamCanBeAppended() { $os1 = new Swift_ByteStream_ArrayByteStream(); $os1->write('abcdef'); $os2 = new Swift_ByteStream_ArrayByteStream(); $os2->write('xyzuvw'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND ); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('abcdefxyzuvw', $this->_cache->getString($this->_key1, 'foo')); } public function testByteStreamAndStringCanBeAppended() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND ); $os = new Swift_ByteStream_ArrayByteStream(); $os->write('abcdef'); $this->_cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testabcdef', $this->_cache->getString($this->_key1, 'foo')); } public function testDataCanBeExportedToByteStream() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $is = new Swift_ByteStream_ArrayByteStream(); $this->_cache->exportToByteStream($this->_key1, 'foo', $is); $string = ''; while (false !== $bytes = $is->read(8192)) { $string .= $bytes; } $this->assertEqual('test', $string); } public function testKeyCanBeCleared() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); $this->_cache->clearKey($this->_key1, 'foo'); $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); } public function testNsKeyCanBeCleared() { $this->_cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->_cache->setString( $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($this->_cache->hasKey($this->_key1, 'foo')); $this->assertTrue($this->_cache->hasKey($this->_key1, 'bar')); $this->_cache->clearAll($this->_key1); $this->assertFalse($this->_cache->hasKey($this->_key1, 'foo')); $this->assertFalse($this->_cache->hasKey($this->_key1, 'bar')); } public function testKeyCacheInputStream() { $is = $this->_cache->getInputByteStream($this->_key1, 'foo'); $is->write('abc'); $is->write('xyz'); $this->assertEqual('abcxyz', $this->_cache->getString($this->_key1, 'foo')); } } Swift-4.2.1/tests/acceptance/Swift/MessageAcceptanceTest.php100644 0 0 3655 12000050367 21173 0ustar 0 0 _createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $boundary = $message->getBoundary(); $message->addPart('foo', 'text/plain', 'iso-8859-1'); $message->addPart('test foo', 'text/html', 'iso-8859-1'); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'test foo' . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } // -- Private helpers protected function _createMessage() { Swift_DependencyContainer::getInstance() ->register('properties.charset')->asValue(null); return Swift_Message::newInstance(); } } Swift-4.2.1/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php100644 0 0 11563 12000050367 22603 0ustar 0 0 _cache = new Swift_KeyCache_ArrayKeyCache( new Swift_KeyCache_SimpleKeyCacheInputStream() ); $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); $this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder(); $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $paramEncoder = new Swift_Encoder_Rfc2231Encoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $this->_grammar = new Swift_Mime_Grammar(); $this->_headers = new Swift_Mime_SimpleHeaderSet( new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar) ); } public function testDispositionIsSetInHeader() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setDisposition('inline'); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline' . "\r\n", $attachment->toString() ); } public function testDispositionIsAttachmentByDefault() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment' . "\r\n", $attachment->toString() ); } public function testFilenameIsSetInHeader() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf' . "\r\n", $attachment->toString() ); } public function testSizeIsSetInHeader() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setSize(12340); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; size=12340' . "\r\n", $attachment->toString() ); } public function testMultipleParametersInHeader() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setSize(12340); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf; size=12340' . "\r\n", $attachment->toString() ); } public function testEndToEnd() { $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setSize(12340); $attachment->setBody('abcd'); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf; size=12340' . "\r\n" . "\r\n" . base64_encode('abcd'), $attachment->toString() ); } // -- Private helpers protected function _createAttachment() { $entity = new Swift_Mime_Attachment( $this->_headers, $this->_contentEncoder, $this->_cache, $this->_grammar ); return $entity; } } Swift-4.2.1/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php100644 0 0 3653 12000050367 27265 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../../_samples/charsets'); $this->_encoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $os = new Swift_ByteStream_ArrayByteStream(); $os->write($text); $is = new Swift_ByteStream_ArrayByteStream(); $this->_encoder->encodeByteStream($os, $is); $encoded = ''; while (false !== $bytes = $is->read(8192)) { $encoded .= $bytes; } $this->assertEqual( base64_decode($encoded), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } } Swift-4.2.1/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php100644 0 0 6055 12000050367 27767 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../../_samples/charsets'); $this->_encoder = new Swift_Mime_ContentEncoder_NativeQpContentEncoder(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $os = new Swift_ByteStream_ArrayByteStream(); $os->write($text); $is = new Swift_ByteStream_ArrayByteStream(); $this->_encoder->encodeByteStream($os, $is); $encoded = ''; while (false !== $bytes = $is->read(8192)) { $encoded .= $bytes; } $this->assertEqual( quoted_printable_decode($encoded), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } public function testEncodingAndDecodingSamplesFromDiConfiguredInstance() { $encoder = $this->_createEncoderFromContainer(); $this->assertSame('=C3=A4=C3=B6=C3=BC=C3=9F', $encoder->encodeString('äöüß')); } public function testCharsetChangeNotImplemented() { $this->_encoder->charsetChanged('utf-8'); $this->expectException(new RuntimeException('Charset "charset" not supported. NativeQpContentEncoder only supports "utf-8"')); $this->_encoder->charsetChanged('charset'); } public function testGetName() { $this->assertSame('quoted-printable', $this->_encoder->getName()); } // -- Private Methods private function _createEncoderFromContainer() { return Swift_DependencyContainer::getInstance() ->lookup('mime.nativeqpcontentencoder') ; } } Swift-4.2.1/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php100644 0 0 6035 12000050367 27301 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../../_samples/charsets'); $this->_encoder = new Swift_Mime_ContentEncoder_PlainContentEncoder('8bit'); } public function testEncodingAndDecodingSamplesString() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $encodedText = $this->_encoder->encodeString($text); $this->assertEqual( $encodedText, $text, '%s: Encoded string should be identical to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } public function testEncodingAndDecodingSamplesByteStream() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $os = new Swift_ByteStream_ArrayByteStream(); $os->write($text); $is = new Swift_ByteStream_ArrayByteStream(); $this->_encoder->encodeByteStream($os, $is); $encoded = ''; while (false !== $bytes = $is->read(8192)) { $encoded .= $bytes; } $this->assertEqual( $encoded, $text, '%s: Encoded string should be identical to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } } Swift-4.2.1/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php100644 0 0 13735 12000050367 26643 0ustar 0 0 _samplesDir = realpath(dirname(__FILE__) . '/../../../../_samples/charsets'); $this->_factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); } public function testEncodingAndDecodingSamples() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $encoding = $encodingDir; $charStream = new Swift_CharacterStream_NgCharacterStream( $this->_factory, $encoding); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $os = new Swift_ByteStream_ArrayByteStream(); $os->write($text); $is = new Swift_ByteStream_ArrayByteStream(); $encoder->encodeByteStream($os, $is); $encoded = ''; while (false !== $bytes = $is->read(8192)) { $encoded .= $bytes; } $this->assertEqual( quoted_printable_decode($encoded), $text, '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } public function testEncodingAndDecodingSamplesFromDiConfiguredInstance() { $sampleFp = opendir($this->_samplesDir); while (false !== $encodingDir = readdir($sampleFp)) { if (substr($encodingDir, 0, 1) == '.') { continue; } $encoding = $encodingDir; $encoder = $this->_createEncoderFromContainer(); $sampleDir = $this->_samplesDir . '/' . $encodingDir; if (is_dir($sampleDir)) { $fileFp = opendir($sampleDir); while (false !== $sampleFile = readdir($fileFp)) { if (substr($sampleFile, 0, 1) == '.') { continue; } $text = file_get_contents($sampleDir . '/' . $sampleFile); $os = new Swift_ByteStream_ArrayByteStream(); $os->write($text); $is = new Swift_ByteStream_ArrayByteStream(); $encoder->encodeByteStream($os, $is); $encoded = ''; while (false !== $bytes = $is->read(8192)) { $encoded .= $bytes; } $this->assertEqual( str_replace("\r\n", "\n", quoted_printable_decode($encoded)), str_replace("\r\n", "\n", $text), '%s: Encoded string should decode back to original string for sample ' . $sampleDir . '/' . $sampleFile ); } closedir($fileFp); } } closedir($sampleFp); } public function testEncodingLFTextWithDiConfiguredInstance() { $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a\r\nb\r\nc", $encoder->encodeString("a\nb\nc")); } public function testEncodingCRTextWithDiConfiguredInstance() { $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a\r\nb\r\nc", $encoder->encodeString("a\rb\rc")); } public function testEncodingLFCRTextWithDiConfiguredInstance() { $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a\r\n\r\nb\r\n\r\nc", $encoder->encodeString("a\n\rb\n\rc")); } public function testEncodingCRLFTextWithDiConfiguredInstance() { $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a\r\nb\r\nc", $encoder->encodeString("a\r\nb\r\nc")); } public function testEncodingDotStuffingWithDiConfiguredInstance() { // Enable DotEscaping Swift_Preferences::getInstance()->setQPDotEscape(true); $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a=2E\r\n=2E\r\n=2Eb\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc")); // Return to default Swift_Preferences::getInstance()->setQPDotEscape(false); $encoder = $this->_createEncoderFromContainer(); $this->assertEqual("a.\r\n.\r\n.b\r\nc", $encoder->encodeString("a.\r\n.\r\n.b\r\nc")); } public function testDotStuffingEncodingAndDecodingSamplesFromDiConfiguredInstance() { // Enable DotEscaping Swift_Preferences::getInstance()->setQPDotEscape(true); $this->testEncodingAndDecodingSamplesFromDiConfiguredInstance(); // Disable DotStuffing to continue Swift_Preferences::getInstance()->setQPDotEscape(false); } // -- Private Methods private function _createEncoderFromContainer() { return Swift_DependencyContainer::getInstance() ->lookup('mime.qpcontentencoder') ; } } Swift-4.2.1/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php100644 0 0 12361 12000050367 23001 0ustar 0 0 _cache = new Swift_KeyCache_ArrayKeyCache( new Swift_KeyCache_SimpleKeyCacheInputStream() ); $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); $this->_contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder(); $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $paramEncoder = new Swift_Encoder_Rfc2231Encoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $this->_grammar = new Swift_Mime_Grammar(); $this->_headers = new Swift_Mime_SimpleHeaderSet( new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar) ); } public function testContentIdIsSetInHeader() { $file = $this->_createEmbeddedFile(); $file->setContentType('application/pdf'); $file->setId('foo@bar'); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline' . "\r\n" . 'Content-ID: ' . "\r\n", $file->toString() ); } public function testDispositionIsSetInHeader() { $file = $this->_createEmbeddedFile(); $id = $file->getId(); $file->setContentType('application/pdf'); $file->setDisposition('attachment'); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment' . "\r\n" . 'Content-ID: <'. $id . '>' . "\r\n", $file->toString() ); } public function testFilenameIsSetInHeader() { $file = $this->_createEmbeddedFile(); $id = $file->getId(); $file->setContentType('application/pdf'); $file->setFilename('foo.pdf'); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=foo.pdf' . "\r\n" . 'Content-ID: <'. $id . '>' . "\r\n", $file->toString() ); } public function testSizeIsSetInHeader() { $file = $this->_createEmbeddedFile(); $id = $file->getId(); $file->setContentType('application/pdf'); $file->setSize(12340); $this->assertEqual( 'Content-Type: application/pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; size=12340' . "\r\n" . 'Content-ID: <'. $id . '>' . "\r\n", $file->toString() ); } public function testMultipleParametersInHeader() { $file = $this->_createEmbeddedFile(); $id = $file->getId(); $file->setContentType('application/pdf'); $file->setFilename('foo.pdf'); $file->setSize(12340); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=foo.pdf; size=12340' . "\r\n" . 'Content-ID: <'. $id . '>' . "\r\n", $file->toString() ); } public function testEndToEnd() { $file = $this->_createEmbeddedFile(); $id = $file->getId(); $file->setContentType('application/pdf'); $file->setFilename('foo.pdf'); $file->setSize(12340); $file->setBody('abcd'); $this->assertEqual( 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=foo.pdf; size=12340' . "\r\n" . 'Content-ID: <'. $id . '>' . "\r\n" . "\r\n" . base64_encode('abcd'), $file->toString() ); } // -- Private helpers protected function _createEmbeddedFile() { $entity = new Swift_Mime_EmbeddedFile( $this->_headers, $this->_contentEncoder, $this->_cache, $this->_grammar ); return $entity; } } Swift-4.2.1/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php100644 0 0 2477 12000050367 26624 0ustar 0 0 _encoder = new Swift_Mime_HeaderEncoder_Base64HeaderEncoder(); } public function testEncodingJIS() { if (function_exists('mb_convert_encoding')) { // base64_encode and split cannot handle long JIS text to fold $subject = "é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„é•·ã„ä»¶å"; $encodedWrapperLength = strlen('=?iso-2022-jp?' . $this->_encoder->getName() . '??='); $old = mb_internal_encoding(); mb_internal_encoding('utf-8'); $newstring = mb_encode_mimeheader($subject, 'iso-2022-jp', 'B', "\r\n"); mb_internal_encoding($old); $encoded = $this->_encoder->encodeString($subject, 0, 75 - $encodedWrapperLength, 'iso-2022-jp'); $this->assertEqual( $encoded, $newstring, 'Encoded string should decode back to original string for sample ' ); } } } Swift-4.2.1/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php100644 0 0 11377 12000050367 22234 0ustar 0 0 _cache = new Swift_KeyCache_ArrayKeyCache( new Swift_KeyCache_SimpleKeyCacheInputStream() ); $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory(); $this->_contentEncoder = new Swift_Mime_ContentEncoder_QpContentEncoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'), new Swift_StreamFilters_ByteArrayReplacementFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ) ); $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $paramEncoder = new Swift_Encoder_Rfc2231Encoder( new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8') ); $this->_grammar = new Swift_Mime_Grammar(); $this->_headers = new Swift_Mime_SimpleHeaderSet( new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $this->_grammar) ); } public function testCharsetIsSetInHeader() { $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('utf-8'); $part->setBody('foobar'); $this->assertEqual( 'Content-Type: text/plain; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foobar', $part->toString() ); } public function testFormatIsSetInHeaders() { $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setFormat('flowed'); $part->setBody('> foobar'); $this->assertEqual( 'Content-Type: text/plain; format=flowed' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . '> foobar', $part->toString() ); } public function testDelSpIsSetInHeaders() { $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setDelSp(true); $part->setBody('foobar'); $this->assertEqual( 'Content-Type: text/plain; delsp=yes' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foobar', $part->toString() ); } public function testAll3ParamsInHeaders() { $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('utf-8'); $part->setFormat('fixed'); $part->setDelSp(true); $part->setBody('foobar'); $this->assertEqual( 'Content-Type: text/plain; charset=utf-8; format=fixed; delsp=yes' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foobar', $part->toString() ); } public function testBodyIsCanonicalized() { $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('utf-8'); $part->setBody("foobar\r\rtest\ning\r"); $this->assertEqual( 'Content-Type: text/plain; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . "foobar\r\n" . "\r\n" . "test\r\n" . "ing\r\n", $part->toString() ); } // -- Private helpers protected function _createMimePart() { $entity = new Swift_Mime_MimePart( $this->_headers, $this->_contentEncoder, $this->_cache, $this->_grammar ); return $entity; } } Swift-4.2.1/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php100644 0 0 135676 12000050367 23305 0ustar 0 0 setCharset(null); //TODO: Test with the charset defined } public function testBasicHeaders() { /* -- RFC 2822, 3.6. */ $message = $this->_createMessage(); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString(), '%s: Only required headers, and non-empty headers should be displayed' ); } public function testSubjectIsDisplayedIfSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testDateCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $id = $message->getId(); $message->setDate(1234); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', 1234) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMessageIdCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setId('foo@bar'); $date = $message->getDate(); $this->assertEqual( 'Message-ID: ' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testContentTypeCanBeChanged() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setContentType('text/html'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/html' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testCharsetCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setContentType('text/html'); $message->setCharset('iso-8859-1'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testFormatCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFormat('flowed'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain; format=flowed' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testEncoderCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setContentType('text/html'); $message->setEncoder( new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit') ); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/html' . "\r\n" . 'Content-Transfer-Encoding: 7bit' . "\r\n", $message->toString() ); } public function testFromAddressCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom('chris.corbyn@swiftmailer.org'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: chris.corbyn@swiftmailer.org' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testFromAddressCanBeSetWithName() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMultipleFromAddressesCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' )); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn , mark@swiftmailer.org' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testReturnPathAddressCanBeSet() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testEmptyReturnPathHeaderCanBeUsed() { $message = $this->_createMessage(); $message->setReturnPath(''); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Return-Path: <>' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testSenderCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setSender('chris.corbyn@swiftmailer.org'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Sender: chris.corbyn@swiftmailer.org' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testSenderCanBeSetWithName() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setSender(array('chris.corbyn@swiftmailer.org'=>'Chris')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Sender: Chris ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testReplyToCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array('chris@w3style.co.uk'=>'Myself')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMultipleReplyAddressCanBeUsed() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testToAddressCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo('mark@swiftmailer.org'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMultipleToAddressesCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo(array( 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn' )); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org, Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testCcAddressCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo(array( 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn' )); $message->setCc('john@some-site.com'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org, Chris Corbyn ' . "\r\n" . 'Cc: john@some-site.com' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMultipleCcAddressesCanBeSet() { $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo(array( 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn' )); $message->setCc(array( 'john@some-site.com' => 'John West', 'fred@another-site.co.uk' => 'Big Fred' )); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org, Chris Corbyn ' . "\r\n" . 'Cc: John West , Big Fred ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testBccAddressCanBeSet() { //Obviously Transports need to setBcc(array()) and send to each Bcc recipient // separately in accordance with RFC 2822/2821 $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo(array( 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn' )); $message->setCc(array( 'john@some-site.com' => 'John West', 'fred@another-site.co.uk' => 'Big Fred' )); $message->setBcc('x@alphabet.tld'); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org, Chris Corbyn ' . "\r\n" . 'Cc: John West , Big Fred ' . "\r\n" . 'Bcc: x@alphabet.tld' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testMultipleBccAddressesCanBeSet() { //Obviously Transports need to setBcc(array()) and send to each Bcc recipient // separately in accordance with RFC 2822/2821 $message = $this->_createMessage(); $message->setSubject('just a test subject'); $message->setFrom(array('chris.corbyn@swiftmailer.org'=>'Chris')); $message->setReplyTo(array( 'chris@w3style.co.uk' => 'Myself', 'my.other@address.com' => 'Me' )); $message->setTo(array( 'mark@swiftmailer.org', 'chris@swiftmailer.org' => 'Chris Corbyn' )); $message->setCc(array( 'john@some-site.com' => 'John West', 'fred@another-site.co.uk' => 'Big Fred' )); $message->setBcc(array('x@alphabet.tld', 'a@alphabet.tld' => 'A')); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris ' . "\r\n" . 'Reply-To: Myself , Me ' . "\r\n" . 'To: mark@swiftmailer.org, Chris Corbyn ' . "\r\n" . 'Cc: John West , Big Fred ' . "\r\n" . 'Bcc: x@alphabet.tld, A ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString() ); } public function testStringBodyIsAppended() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setBody( 'just a test body' . "\r\n" . 'with a new line' ); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'just a test body' . "\r\n" . 'with a new line', $message->toString() ); } public function testStringBodyIsEncoded() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setBody( 'Just s' . pack('C*', 0xC2, 0x01, 0x01) . 'me multi-' . "\r\n" . 'line message!' ); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'Just s=C2=01=01me multi-' . "\r\n" . 'line message!', $message->toString() ); } public function testChildrenCanBeAttached() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $boundary = $message->getBoundary(); $part1 = $this->_createMimePart(); $part1->setContentType('text/plain'); $part1->setCharset('iso-8859-1'); $part1->setBody('foo'); $message->attach($part1); $part2 = $this->_createMimePart(); $part2->setContentType('text/html'); $part2->setCharset('iso-8859-1'); $part2->setBody('test foo'); $message->attach($part2); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'test foo' . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } public function testAttachmentsBeingAttached() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('iso-8859-1'); $part->setBody('foo'); $message->attach($part); $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setBody(''); $message->attach($attachment); $this->assertPattern( '~^' . 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString() ); } public function testAttachmentsAndEmbeddedFilesBeingAttached() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('iso-8859-1'); $part->setBody('foo'); $message->attach($part); $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setBody(''); $message->attach($attachment); $file = $this->_createEmbeddedFile(); $file->setContentType('image/jpeg'); $file->setFilename('myimage.jpg'); $file->setBody(''); $message->attach($file); $cid = $file->getId(); $this->assertPattern( '~^' . 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\2' . "\r\n" . 'Content-Type: image/jpeg; name=myimage.jpg' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=myimage.jpg' . "\r\n" . 'Content-ID: <' . $cid . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--\\2--' . "\r\n" . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString() ); } public function testComplexEmbeddingOfContent() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setBody(''); $message->attach($attachment); $file = $this->_createEmbeddedFile(); $file->setContentType('image/jpeg'); $file->setFilename('myimage.jpg'); $file->setBody(''); $part = $this->_createMimePart(); $part->setContentType('text/html'); $part->setCharset('iso-8859-1'); $part->setBody('foo '); $message->attach($part); $cid = $file->getId(); $this->assertPattern( '~^' . 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo ' . //=3D is just = in QP "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: image/jpeg; name=myimage.jpg' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=myimage.jpg' . "\r\n" . 'Content-ID: <' . $cid . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString() ); } public function testAttachingAndDetachingContent() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $part = $this->_createMimePart(); $part->setContentType('text/plain'); $part->setCharset('iso-8859-1'); $part->setBody('foo'); $message->attach($part); $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setBody(''); $message->attach($attachment); $file = $this->_createEmbeddedFile(); $file->setContentType('image/jpeg'); $file->setFilename('myimage.jpg'); $file->setBody(''); $message->attach($file); $cid = $file->getId(); $message->detach($attachment); $this->assertPattern( '~^' . 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: image/jpeg; name=myimage.jpg' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=myimage.jpg' . "\r\n" . 'Content-ID: <' . $cid . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString(), '%s: Attachment should have been detached' ); } public function testBoundaryDoesNotAppearAfterAllPartsAreDetached() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = $message->getDate(); $boundary = $message->getBoundary(); $part1 = $this->_createMimePart(); $part1->setContentType('text/plain'); $part1->setCharset('iso-8859-1'); $part1->setBody('foo'); $message->attach($part1); $part2 = $this->_createMimePart(); $part2->setContentType('text/html'); $part2->setCharset('iso-8859-1'); $part2->setBody('test foo'); $message->attach($part2); $message->detach($part1); $message->detach($part2); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n", $message->toString(), '%s: Message should be restored to orignal state after parts are detached' ); } public function testCharsetFormatOrDelSpAreNotShownWhenBoundaryIsSet() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setCharset('utf-8'); $message->setFormat('flowed'); $message->setDelSp(true); $id = $message->getId(); $date = $message->getDate(); $boundary = $message->getBoundary(); $part1 = $this->_createMimePart(); $part1->setContentType('text/plain'); $part1->setCharset('iso-8859-1'); $part1->setBody('foo'); $message->attach($part1); $part2 = $this->_createMimePart(); $part2->setContentType('text/html'); $part2->setCharset('iso-8859-1'); $part2->setBody('test foo'); $message->attach($part2); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'test foo' . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } public function testBodyCanBeSetWithAttachments() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setContentType('text/html'); $message->setCharset('iso-8859-1'); $message->setBody('foo'); $id = $message->getId(); $date = date('r', $message->getDate()); $boundary = $message->getBoundary(); $attachment = $this->_createAttachment(); $attachment->setContentType('application/pdf'); $attachment->setFilename('foo.pdf'); $attachment->setBody(''); $message->attach($attachment); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=iso-8859-1' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: application/pdf; name=foo.pdf' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=foo.pdf' . "\r\n" . "\r\n" . base64_encode('') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } public function testHtmlPartAlwaysAppearsLast() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $id = $message->getId(); $date = date('r', $message->getDate()); $boundary = $message->getBoundary(); $part1 = $this->_createMimePart(); $part1->setContentType('text/html'); $part1->setBody('foo'); $part2 = $this->_createMimePart(); $part2->setContentType('text/plain'); $part2->setBody('bar'); $message->attach($part1); $message->attach($part2); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'bar' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } public function testBodyBecomesPartIfOtherPartsAttached() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setContentType('text/html'); $message->setBody('foo'); $id = $message->getId(); $date = date('r', $message->getDate()); $boundary = $message->getBoundary(); $part2 = $this->_createMimePart(); $part2->setContentType('text/plain'); $part2->setBody('bar'); $message->attach($part2); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'bar' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'foo' . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n", $message->toString() ); } public function testBodyIsCanonicalized() { $message = $this->_createMessage(); $message->setReturnPath('chris@w3style.co.uk'); $message->setSubject('just a test subject'); $message->setFrom(array( 'chris.corbyn@swiftmailer.org' => 'Chris Corbyn')); $message->setBody( 'just a test body' . "\n" . 'with a new line' ); $id = $message->getId(); $date = $message->getDate(); $this->assertEqual( 'Return-Path: ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . date('r', $date) . "\r\n" . 'Subject: just a test subject' . "\r\n" . 'From: Chris Corbyn ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: text/plain' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'just a test body' . "\r\n" . 'with a new line', $message->toString() ); } // -- Private helpers protected function _createMessage() { return new Swift_Message(); } protected function _createMimePart() { return new Swift_MimePart(); } protected function _createAttachment() { return new Swift_Attachment(); } protected function _createEmbeddedFile() { return new Swift_EmbeddedFile(); } } Swift-4.2.1/tests/acceptance/Swift/MimePartAcceptanceTest.php100644 0 0 603 12000050367 21273 0ustar 0 0 register('properties.charset')->asValue(null); return Swift_MimePart::newInstance(); } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php100644 0 0 6435 12000050367 30240 0ustar 0 0 _buffer = new Swift_Transport_StreamBuffer( $this->_stub('Swift_ReplacementFilterFactory') ); } public function testReadLine() { $this->_initializeBuffer(); $line = $this->_buffer->readLine(0); $this->assertPattern('/^[0-9]{3}.*?\r\n$/D', $line); $seq = $this->_buffer->write("QUIT\r\n"); $this->assertTrue($seq); $line = $this->_buffer->readLine($seq); $this->assertPattern('/^[0-9]{3}.*?\r\n$/D', $line); $this->_buffer->terminate(); } public function testWrite() { $this->_initializeBuffer(); $line = $this->_buffer->readLine(0); $this->assertPattern('/^[0-9]{3}.*?\r\n$/D', $line); $seq = $this->_buffer->write("HELO foo\r\n"); $this->assertTrue($seq); $line = $this->_buffer->readLine($seq); $this->assertPattern('/^[0-9]{3}.*?\r\n$/D', $line); $seq = $this->_buffer->write("QUIT\r\n"); $this->assertTrue($seq); $line = $this->_buffer->readLine($seq); $this->assertPattern('/^[0-9]{3}.*?\r\n$/D', $line); $this->_buffer->terminate(); } public function testBindingOtherStreamsMirrorsWriteOperations() { $this->_initializeBuffer(); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') -> one($is2)->write('y') ); $this->_buffer->bind($is1); $this->_buffer->bind($is2); $this->_buffer->write('x'); $this->_buffer->write('y'); } public function testBindingOtherStreamsMirrorsFlushOperations() { $this->_initializeBuffer(); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->flushBuffers() -> one($is2)->flushBuffers() ); $this->_buffer->bind($is1); $this->_buffer->bind($is2); $this->_buffer->flushBuffers(); } public function testUnbindingStreamPreventsFurtherWrites() { $this->_initializeBuffer(); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') ); $this->_buffer->bind($is1); $this->_buffer->bind($is2); $this->_buffer->write('x'); $this->_buffer->unbind($is2); $this->_buffer->write('y'); } // -- Creation Methods private function _createMockInputStream() { return $this->_mock('Swift_InputByteStream'); } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php100644 0 0 1661 12000050367 26355 0ustar 0 0 skipUnless(SWIFT_SMTP_HOST, 'Cannot run test without an SMTP host to connect to (define ' . 'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)' ); } protected function _initializeBuffer() { $parts = explode(':', SWIFT_SMTP_HOST); $host = $parts[0]; $port = isset($parts[1]) ? $parts[1] : 25; $this->_buffer->initialize(array( 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, 'host' => $host, 'port' => $port, 'protocol' => 'tcp', 'blocking' => 1, 'timeout' => 15 )); } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php100644 0 0 1316 12000050367 25576 0ustar 0 0 skipIf(!SWIFT_SENDMAIL_PATH, 'Cannot run test without a path to sendmail (define ' . 'SWIFT_SENDMAIL_PATH in tests/acceptance.conf.php if you wish to run this test)' ); } protected function _initializeBuffer() { $this->_buffer->initialize(array( 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, 'command' => SWIFT_SENDMAIL_PATH . ' -bs' )); } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php100644 0 0 4030 12000050367 25004 0ustar 0 0 _buffer = new Swift_Transport_StreamBuffer( $this->_stub('Swift_ReplacementFilterFactory') ); } public function skip() { $serverStarted=false; for ($i=0; $i<5; ++$i) { $this->_randomHighPort=rand(50000,65000); $this->_server = stream_socket_server('tcp://127.0.0.1:' . $this->_randomHighPort); if ($this->_server) { $serverStarted=true; } } $this->skipUnless(SWIFT_SMTP_HOST, 'Cannot run test without an SMTP host to connect to (define ' . 'SWIFT_SMTP_HOST in tests/acceptance.conf.php if you wish to run this test)' ); } protected function _initializeBuffer() { $host = '127.0.0.1'; $port = $this->_randomHighPort; $this->_buffer->initialize(array( 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, 'host' => $host, 'port' => $port, 'protocol' => 'tcp', 'blocking' => 1, 'timeout' => 1 )); } public function testTimeoutException() { $this->_initializeBuffer(); $e=null; try { $line = $this->_buffer->readLine(0); } catch (Exception $e) { } $this->assertIsA($e, 'Swift_IoException', 'IO Exception Not Thrown On Connection Timeout'); $this->assertPattern('/Connection to .* Timed Out/', $e->getMessage()); } public function tearDown() { if ($this->_server) { stream_socket_shutdown($this->_server, STREAM_SHUT_RDWR); } } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php100644 0 0 2174 12000050367 26075 0ustar 0 0 skipIf(!in_array('ssl', $streams), 'SSL is not configured for your system. It is not possible to run this test' ); $this->skipIf(!SWIFT_SSL_HOST, 'Cannot run test without an SSL enabled SMTP host to connect to (define ' . 'SWIFT_SSL_HOST in tests/acceptance.conf.php if you wish to run this test)' ); } protected function _initializeBuffer() { $parts = explode(':', SWIFT_SSL_HOST); $host = $parts[0]; $port = isset($parts[1]) ? $parts[1] : 25; $this->_buffer->initialize(array( 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, 'host' => $host, 'port' => $port, 'protocol' => 'ssl', 'blocking' => 1, 'timeout' => 15 )); } } Swift-4.2.1/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php100644 0 0 2173 12000050367 26075 0ustar 0 0 skipIf(!in_array('tls', $streams), 'TLS is not configured for your system. It is not possible to run this test' ); $this->skipIf(!SWIFT_TLS_HOST, 'Cannot run test without a TLS enabled SMTP host to connect to (define ' . 'SWIFT_TLS_HOST in tests/acceptance.conf.php if you wish to run this test)' ); } protected function _initializeBuffer() { $parts = explode(':', SWIFT_TLS_HOST); $host = $parts[0]; $port = isset($parts[1]) ? $parts[1] : 25; $this->_buffer->initialize(array( 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, 'host' => $host, 'port' => $port, 'protocol' => 'tls', 'blocking' => 1, 'timeout' => 15 )); } } Swift-4.2.1/tests/bug/Swift/Bug111Test.php100644 0 0 2536 12000050367 15264 0ustar 0 0 array( 'email1@example.com', 'email2@example.com', 'email3@example.com', 'email4@example.com', 'email5@example.com', ), 'sub' => array( '-name-' => array( 'email1', '"email2"', 'email3\\', 'email4', 'email5', ), '-url-' => array( 'http://google.com', 'http://yahoo.com', 'http://hotmail.com', 'http://aol.com', 'http://facebook.com', ), ) ); $json = json_encode($complicated_header); $message = new Swift_Message(); $headers = $message->getHeaders(); $headers->addTextHeader('X-SMTPAPI', $json); $header = $headers->get('X-SMTPAPI'); $this->assertEqual('Swift_Mime_Headers_UnstructuredHeader', get_class($header)); $this->assertEqual($json, $header->getFieldBody()); } } Swift-4.2.1/tests/bug/Swift/Bug118Test.php100644 0 0 753 12000050367 15252 0ustar 0 0 _message = new Swift_Message(); } public function testCallingGenerateIdChangesTheMessageId() { $currentId = $this->_message->getId(); $this->_message->generateId(); $newId = $this->_message->getId(); $this->assertNotEqual($currentId, $newId); } } Swift-4.2.1/tests/bug/Swift/Bug206Test.php100644 0 0 3137 12000050367 15267 0ustar 0 0 _factory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $grammar); } public function testMailboxHeaderEncoding() { $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Name, Name', ' "Family Name, Name" '); $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé, Name', ' Family =?utf-8?Q?Nam=C3=A9=2C?= Name'); $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé , Name', ' Family =?utf-8?Q?Nam=C3=A9_=2C?= Name'); $this->_testHeaderIsFullyEncoded('email@example.org', 'Family Namé ;Name', ' Family =?utf-8?Q?Nam=C3=A9_=3BName?= '); } private function _testHeaderIsFullyEncoded($email, $name, $expected) { $mailboxHeader = $this->_factory->createMailboxHeader('To', array( $email => $name )); $headerBody = substr($mailboxHeader->toString(), 3, strlen($expected)); $this->assertEqual($expected, $headerBody); } } Swift-4.2.1/tests/bug/Swift/Bug34Test.php100644 0 0 5175 12000050367 15212 0ustar 0 0 setCharset('utf-8'); } public function testEmbeddedFilesWithMultipartDataCreateMultipartRelatedContentAsAnAlternative() { $message = Swift_Message::newInstance(); $message->setCharset('utf-8'); $message->setSubject('test subject'); $message->addPart('plain part', 'text/plain'); $image = Swift_Image::newInstance('', 'image.gif', 'image/gif'); $cid = $message->embed($image); $message->setBody('', 'text/html'); $message->setTo(array('user@domain.tld' => 'User')); $message->setFrom(array('other@domain.tld' => 'Other')); $message->setSender(array('other@domain.tld' => 'Other')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $cidVal = $image->getId(); $this->assertPattern( '~^' . 'Sender: Other ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: Other ' . "\r\n" . 'To: User ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'plain part' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . '' . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: image/gif; name=image.gif' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=image.gif' . "\r\n" . 'Content-ID: <' . $cidVal . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString() ); } } Swift-4.2.1/tests/bug/Swift/Bug35Test.php100644 0 0 4766 12000050367 15220 0ustar 0 0 setCharset('utf-8'); } public function testHTMLPartAppearsLastEvenWhenAttachmentsAdded() { $message = Swift_Message::newInstance(); $message->setCharset('utf-8'); $message->setSubject('test subject'); $message->addPart('plain part', 'text/plain'); $attachment = Swift_Attachment::newInstance('', 'image.gif', 'image/gif'); $message->attach($attachment); $message->setBody('HTML part', 'text/html'); $message->setTo(array('user@domain.tld' => 'User')); $message->setFrom(array('other@domain.tld' => 'Other')); $message->setSender(array('other@domain.tld' => 'Other')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $this->assertPattern( '~^' . 'Sender: Other ' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: Other ' . "\r\n" . 'To: User ' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/plain; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'plain part' . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'HTML part' . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: image/gif; name=image.gif' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=image.gif' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString() ); } } Swift-4.2.1/tests/bug/Swift/Bug38Test.php100644 0 0 15561 12000050367 15236 0ustar 0 0 _attFileName = 'data.txt'; $this->_attFileType = 'text/plain'; $this->_attFile = dirname(__FILE__) . '/../../_samples/files/data.txt'; Swift_Preferences::getInstance()->setCharset('utf-8'); } public function testWritingMessageToByteStreamProducesCorrectStructure() { $message = new Swift_Message(); $message->setSubject('test subject'); $message->setTo('user@domain.tld'); $message->setCc('other@domain.tld'); $message->setFrom('user@domain.tld'); $image = new Swift_Image('', 'image.gif', 'image/gif'); $cid = $message->embed($image); $message->setBody('HTML part', 'text/html'); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $imgId = $image->getId(); $stream = new Swift_ByteStream_ArrayByteStream(); $message->toByteStream($stream); $this->assertPatternInStream( '~^' . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: user@domain.tld' . "\r\n" . 'To: user@domain.tld' . "\r\n" . 'Cc: other@domain.tld' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'HTML part' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: image/gif; name=image.gif' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=image.gif' . "\r\n" . 'Content-ID: <' . preg_quote($imgId, '~') . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $stream ); } public function testWritingMessageToByteStreamTwiceProducesCorrectStructure() { $message = new Swift_Message(); $message->setSubject('test subject'); $message->setTo('user@domain.tld'); $message->setCc('other@domain.tld'); $message->setFrom('user@domain.tld'); $image = new Swift_Image('', 'image.gif', 'image/gif'); $cid = $message->embed($image); $message->setBody('HTML part', 'text/html'); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $imgId = $image->getId(); $pattern = '~^' . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: user@domain.tld' . "\r\n" . 'To: user@domain.tld' . "\r\n" . 'Cc: other@domain.tld' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'HTML part' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: image/gif; name=image.gif' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=image.gif' . "\r\n" . 'Content-ID: <' . preg_quote($imgId, '~') . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode(''), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D' ; $streamA = new Swift_ByteStream_ArrayByteStream(); $streamB = new Swift_ByteStream_ArrayByteStream(); $message->toByteStream($streamA); $message->toByteStream($streamB); $this->assertPatternInStream($pattern, $streamA); $this->assertPatternInStream($pattern, $streamB); } public function testWritingMessageToByteStreamTwiceUsingAFileAttachment() { $message = new Swift_Message(); $message->setSubject('test subject'); $message->setTo('user@domain.tld'); $message->setCc('other@domain.tld'); $message->setFrom('user@domain.tld'); $attachment = Swift_Attachment::fromPath($this->_attFile); $message->attach($attachment); $message->setBody('HTML part', 'text/html'); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $streamA = new Swift_ByteStream_ArrayByteStream(); $streamB = new Swift_ByteStream_ArrayByteStream(); $pattern = '~^' . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: user@domain.tld' . "\r\n" . 'To: user@domain.tld' . "\r\n" . 'Cc: other@domain.tld' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/mixed;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'HTML part' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: ' . $this->_attFileType . '; name=' . $this->_attFileName . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: attachment; filename=' . $this->_attFileName . "\r\n" . "\r\n" . preg_quote(base64_encode(file_get_contents($this->_attFile)), '~') . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D' ; $message->toByteStream($streamA); $message->toByteStream($streamB); $this->assertPatternInStream($pattern, $streamA); $this->assertPatternInStream($pattern, $streamB); } // -- Helpers public function assertPatternInStream($pattern, $stream, $message = '%s') { $string = ''; while (false !== $bytes = $stream->read(8192)) { $string .= $bytes; } $this->assertPattern($pattern, $string, $message); } } Swift-4.2.1/tests/bug/Swift/Bug51Test.php100644 0 0 7243 12000050367 15207 0ustar 0 0 skipUnless( is_writable(SWIFT_TMP_DIR), '%s: This test requires tests/acceptance.conf.php to specify a ' . 'writable SWIFT_TMP_DIR' ); } public function setUp() { $this->_attachmentFile = SWIFT_TMP_DIR . '/attach.rand.bin'; file_put_contents($this->_attachmentFile, ''); $this->_outputFile = SWIFT_TMP_DIR . '/attach.out.bin'; file_put_contents($this->_outputFile, ''); } public function tearDown() { unlink($this->_attachmentFile); unlink($this->_outputFile); } public function testAttachmentsDoNotGetTruncatedUsingToByteStream() { //Run 100 times with 10KB attachments for ($i = 0; $i < 10; ++$i) { $message = $this->_createMessageWithRandomAttachment( 10000, $this->_attachmentFile ); file_put_contents($this->_outputFile, ''); $message->toByteStream( new Swift_ByteStream_FileByteStream($this->_outputFile, true) ); $emailSource = file_get_contents($this->_outputFile); $this->assertAttachmentFromSourceMatches( file_get_contents($this->_attachmentFile), $emailSource ); } } public function testAttachmentsDoNotGetTruncatedUsingToString() { //Run 100 times with 10KB attachments for ($i = 0; $i < 10; ++$i) { $message = $this->_createMessageWithRandomAttachment( 10000, $this->_attachmentFile ); $emailSource = $message->toString(); $this->assertAttachmentFromSourceMatches( file_get_contents($this->_attachmentFile), $emailSource ); } } // -- Custom Assertions public function assertAttachmentFromSourceMatches($attachmentData, $source) { $encHeader = 'Content-Transfer-Encoding: base64'; $base64declaration = strpos($source, $encHeader); $attachmentDataStart = strpos($source, "\r\n\r\n", $base64declaration); $attachmentDataEnd = strpos($source, "\r\n--", $attachmentDataStart); if (false === $attachmentDataEnd) { $attachmentBase64 = trim(substr($source, $attachmentDataStart)); } else { $attachmentBase64 = trim(substr( $source, $attachmentDataStart, $attachmentDataEnd - $attachmentDataStart )); } $this->assertIdenticalBinary($attachmentData, base64_decode($attachmentBase64)); } // -- Creation Methods private function _fillFileWithRandomBytes($byteCount, $file) { // I was going to use dd with if=/dev/random but this way seems more // cross platform even if a hella expensive!! file_put_contents($file, ''); $fp = fopen($file, 'wb'); for ($i = 0; $i < $byteCount; ++$i) { $byteVal = rand(0, 255); fwrite($fp, pack('i', $byteVal)); } fclose($fp); } private function _createMessageWithRandomAttachment($size, $attachmentPath) { $this->_fillFileWithRandomBytes($size, $attachmentPath); $message = Swift_Message::newInstance() ->setSubject('test') ->setBody('test') ->setFrom('a@b.c') ->setTo('d@e.f') ->attach(Swift_Attachment::fromPath($attachmentPath)) ; return $message; } } Swift-4.2.1/tests/bug/Swift/Bug71Test.php100644 0 0 1053 12000050367 15202 0ustar 0 0 _message = new Swift_Message('test'); } public function testCallingToStringAfterSettingNewBodyReflectsChanges() { $this->_message->setBody('BODY1'); $this->assertPattern('/BODY1/', $this->_message->toString()); $this->_message->setBody('BODY2'); $this->assertPattern('/BODY2/', $this->_message->toString()); } } Swift-4.2.1/tests/bug/Swift/Bug76Test.php100644 0 0 4413 12000050367 15212 0ustar 0 0 skipUnless( is_writable(SWIFT_TMP_DIR), '%s: This test requires tests/acceptance.conf.php to specify a ' . 'writable SWIFT_TMP_DIR' ); } public function setUp() { $this->_inputFile = SWIFT_TMP_DIR . '/in.bin'; file_put_contents($this->_inputFile, ''); $this->_outputFile = SWIFT_TMP_DIR . '/out.bin'; file_put_contents($this->_outputFile, ''); $this->_encoder = $this->_createEncoder(); } public function tearDown() { unlink($this->_inputFile); unlink($this->_outputFile); } public function testBase64EncodedLineLengthNeverExceeds76CharactersEvenIfArgsDo() { $this->_fillFileWithRandomBytes(1000, $this->_inputFile); $os = $this->_createStream($this->_inputFile); $is = $this->_createStream($this->_outputFile); $this->_encoder->encodeByteStream($os, $is, 0, 80); //Exceeds 76 $this->assertMaxLineLength(76, $this->_outputFile, '%s: Line length should not exceed 76 characters' ); } // -- Custom Assertions public function assertMaxLineLength($length, $filePath, $message = '%s') { $lines = file($filePath); foreach ($lines as $line) { $this->assertTrue((strlen(trim($line)) <= 76), $message); } } // -- Creation Methods private function _fillFileWithRandomBytes($byteCount, $file) { // I was going to use dd with if=/dev/random but this way seems more // cross platform even if a hella expensive!! file_put_contents($file, ''); $fp = fopen($file, 'wb'); for ($i = 0; $i < $byteCount; ++$i) { $byteVal = rand(0, 255); fwrite($fp, pack('i', $byteVal)); } fclose($fp); } private function _createEncoder() { return new Swift_Mime_ContentEncoder_Base64ContentEncoder(); } private function _createStream($file) { return new Swift_ByteStream_FileByteStream($file, true); } } Swift-4.2.1/tests/helpers/Swift/Tests/IdenticalBinaryExpectation.php100644 0 0 3660 12000050367 22717 0ustar 0 0 _left = $left; } /** * Get the given string of bytes as a stirng of Hexadecimal sequences. * @param string $binary * @return string */ public function asHexString($binary) { $hex = ''; $bytes = unpack('H*', $binary); foreach ($bytes as &$byte) { $byte = strtoupper($byte); } return implode('', $bytes); } /** * Test that the passed subject ($right) is identical to $left. * @param string $right, subject * @return boolean */ public function test($right) { $aHex = $this->asHexString($this->_left); $bHex = $this->asHexString($right); return $aHex === $bHex; } /** * Get the message depending upon whether this expectation is satisfied. * @param $right subject to compare against * @return string */ public function testMessage($right) { if ($this->test($right)) { return 'Identical binary expectation [' . $this->asHexString($right) . ']'; } else { $this->_dumper=new SimpleDumper(); return 'Identical binary expectation fails ' . $this->_dumper->describeDifference( $this->asHexString($this->_left), $this->asHexString($right) ); } } } Swift-4.2.1/tests/helpers/Swift/Tests/SwiftSmokeTestCase.php100644 0 0 3246 12000050367 21201 0ustar 0 0 skipUnless(SWIFT_SMOKE_TRANSPORT_TYPE, '%s: Smoke tests are skipped if tests/smoke.conf.php is not editted' ); } protected function _getMailer() { switch (SWIFT_SMOKE_TRANSPORT_TYPE) { case 'smtp': $transport = Swift_DependencyContainer::getInstance()->lookup('transport.smtp') ->setHost(SWIFT_SMOKE_SMTP_HOST) ->setPort(SWIFT_SMOKE_SMTP_PORT) ->setUsername(SWIFT_SMOKE_SMTP_USER) ->setPassword(SWIFT_SMOKE_SMTP_PASS) ->setEncryption(SWIFT_SMOKE_SMTP_ENCRYPTION) ; break; case 'sendmail': $transport = Swift_DependencyContainer::getInstance()->lookup('transport.sendmail') ->setCommand(SWIFT_SMOKE_SENDMAIL_COMMAND) ; break; case 'mail': case 'nativemail': $transport = Swift_DependencyContainer::getInstance()->lookup('transport.mail'); break; default: throw new Exception('Undefined transport [' . SWIFT_SMOKE_TRANSPORT_TYPE . ']'); } return new Swift_Mailer($transport); } protected function _visualCheck($url) { $this->dump('{image @ ' . $url . '}'); } } Swift-4.2.1/tests/helpers/Swift/Tests/SwiftUnitTestCase.php100644 0 0 4412 12000050367 21036 0ustar 0 0 _mockery()->assertIsSatisfied(); } catch (Yay_NotSatisfiedException $e) { $this->fail($e->getMessage()); } $this->_mockery = null; return parent::after($method); } /** * Assert two binary strings are an exact match. * @param string $a * @param string $b * @param string $s formatted message */ public function assertIdenticalBinary($a, $b, $s = '%s') { return $this->assert(new Swift_Tests_IdenticalBinaryExpectation($a), $b, $s); } // -- Protected methods /** * Returns a singleton-per-test method for Yay_Mockery. * @return Yay_Mockery */ protected function _mockery() { if (!isset($this->_mockery)) { $this->_mockery = new Yay_Mockery(); } return $this->_mockery; } /** * Create a mock object. * @param string $class * @return Yay_Mock */ protected function _mock($class) { return $this->_mockery()->mock($class); } /** * Add mock expectations. * @param Yay_Expectations $expectations */ protected function _checking($expectations) { return $this->_mockery()->checking($expectations); } /** * Create a mock object which does nothing. * @param string $class * @return Yay_Mock */ protected function _stub($class) { $stub = $this->_mockery()->mock($class); $this->_mockery()->checking(Yay_Expectations::create() -> ignoring($stub) ); return $stub; } protected function _states($machineName) { return $this->_mockery()->states($machineName); } protected function _sequence($sequenceName) { return $this->_mockery()->sequence($sequenceName); } } Swift-4.2.1/tests/smoke.conf.php100644 0 0 2744 12000050367 13656 0ustar 0 0 _attFile = dirname(__FILE__) . '/../../../_samples/files/textfile.zip'; } public function testAttachmentSending() { $mailer = $this->_getMailer(); $message = Swift_Message::newInstance() ->setSubject('[Swift Mailer] AttachmentSmokeTest') ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer')) ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS) ->setBody('This message should contain an attached ZIP file (named "textfile.zip").' . PHP_EOL . 'When unzipped, the archive should produce a text file which reads:' . PHP_EOL . '"This is part of a Swift Mailer v4 smoke test."' ) ->attach(Swift_Attachment::fromPath($this->_attFile)) ; $this->assertEqual(1, $mailer->send($message), '%s: The smoke test should send a single message' ); $this->_visualCheck('http://swiftmailer.org/smoke/4.0.0/attachment.jpg'); } } Swift-4.2.1/tests/smoke/Swift/Smoke/BasicSmokeTest.php100644 0 0 1502 12000050367 17753 0ustar 0 0 _getMailer(); $message = Swift_Message::newInstance() ->setSubject('[Swift Mailer] BasicSmokeTest') ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer')) ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS) ->setBody('One, two, three, four, five...' . PHP_EOL . 'six, seven, eight...' ) ; $this->assertEqual(1, $mailer->send($message), '%s: The smoke test should send a single message' ); $this->_visualCheck('http://swiftmailer.org/smoke/4.0.0/basic.jpg'); } } Swift-4.2.1/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php100644 0 0 2277 12000050367 22515 0ustar 0 0 _attFile = dirname(__FILE__) . '/../../../_samples/files/textfile.zip'; } public function testAttachmentSending() { $mailer = $this->_getMailer(); $message = Swift_Message::newInstance('[Swift Mailer] HtmlWithAttachmentSmokeTest') ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'Swift Mailer')) ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS) ->attach(Swift_Attachment::fromPath($this->_attFile)) ->setBody('

This HTML-formatted message should contain an attached ZIP file (named "textfile.zip").' . PHP_EOL . 'When unzipped, the archive should produce a text file which reads:

' . PHP_EOL . '

This is part of a Swift Mailer v4 smoke test.

', 'text/html' ) ; $this->assertEqual(1, $mailer->send($message), '%s: The smoke test should send a single message' ); $this->_visualCheck('http://swiftmailer.org/smoke/4.0.0/attachment.jpg'); } } Swift-4.2.1/tests/smoke/Swift/Smoke/InternationalSmokeTest.php100644 0 0 3103 12000050367 21540 0ustar 0 0 _attFile = dirname(__FILE__) . '/../../../_samples/files/textfile.zip'; } public function testAttachmentSending() { $mailer = $this->_getMailer(); $message = Swift_Message::newInstance() ->setCharset('utf-8') ->setSubject('[Swift Mailer] InternationalSmokeTest (διεθνής)') ->setFrom(array(SWIFT_SMOKE_EMAIL_ADDRESS => 'ΧÏιστοφοÏου (Swift Mailer)')) ->setTo(SWIFT_SMOKE_EMAIL_ADDRESS) ->setBody('This message should contain an attached ZIP file (named "κείμενο, εδάφιο, θέμα.zip").' . PHP_EOL . 'When unzipped, the archive should produce a text file which reads:' . PHP_EOL . '"This is part of a Swift Mailer v4 smoke test."' . PHP_EOL . PHP_EOL . 'Following is some arbitrary Greek text:' . PHP_EOL . 'Δεν βÏέθηκαν λέξεις.' ) ->attach(Swift_Attachment::fromPath($this->_attFile) ->setContentType('application/zip') ->setFilename('κείμενο, εδάφιο, θέμα.zip') ) ; $this->assertEqual(1, $mailer->send($message), '%s: The smoke test should send a single message' ); $this->_visualCheck('http://swiftmailer.org/smoke/4.0.0/international.jpg'); } } Swift-4.2.1/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php100644 0 0 13231 12000050367 21675 0ustar 0 0 _createArrayStream($input); $output = array(); while (false !== $bytes = $bs->read(1)) { $output[] = $bytes; } $this->assertEqual($input, $output, '%s: Bytes read from stream should be the same as bytes in constructor' ); } public function testReadingMultipleBytesFromBaseInput() { $input = array('a', 'b', 'c', 'd'); $bs = $this->_createArrayStream($input); $output = array(); while (false !== $bytes = $bs->read(2)) { $output[] = $bytes; } $this->assertEqual(array('ab', 'cd'), $output, '%s: Bytes read from stream should be in pairs' ); } public function testReadingOddOffsetOnLastByte() { $input = array('a', 'b', 'c', 'd', 'e'); $bs = $this->_createArrayStream($input); $output = array(); while (false !== $bytes = $bs->read(2)) { $output[] = $bytes; } $this->assertEqual(array('ab', 'cd', 'e'), $output, '%s: Bytes read from stream should be in pairs except final read' ); } public function testSettingPointerPartway() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); $bs->setReadPointer(1); $this->assertEqual('b', $bs->read(1), '%s: Byte should be second byte since pointer as at offset 1' ); } public function testResettingPointerAfterExhaustion() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); while (false !== $bs->read(1)); $bs->setReadPointer(0); $this->assertEqual('a', $bs->read(1), '%s: Byte should be first byte since pointer as at offset 0' ); } public function testPointerNeverSetsBelowZero() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); $bs->setReadPointer(-1); $this->assertEqual('a', $bs->read(1), '%s: Byte should be first byte since pointer should be at offset 0' ); } public function testPointerNeverSetsAboveStackSize() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); $bs->setReadPointer(3); $this->assertIdentical(false, $bs->read(1), '%s: Stream should be at end and thus return false' ); } public function testBytesCanBeWrittenToStream() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); $bs->write('de'); $output = array(); while (false !== $bytes = $bs->read(1)) { $output[] = $bytes; } $this->assertEqual(array('a', 'b', 'c', 'd', 'e'), $output, '%s: Bytes read from stream should be from initial stack + written' ); } public function testContentsCanBeFlushed() { $input = array('a', 'b', 'c'); $bs = $this->_createArrayStream($input); $bs->flushBuffers(); $this->assertIdentical(false, $bs->read(1), '%s: Contents have been flushed so read() should return false' ); } public function testConstructorCanTakeStringArgument() { $bs = $this->_createArrayStream('abc'); $output = array(); while (false !== $bytes = $bs->read(1)) { $output[] = $bytes; } $this->assertEqual(array('a', 'b', 'c'), $output, '%s: Bytes read from stream should be the same as bytes in constructor' ); } public function testBindingOtherStreamsMirrorsWriteOperations() { $bs = $this->_createArrayStream(''); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') -> one($is2)->write('y') ); $bs->bind($is1); $bs->bind($is2); $bs->write('x'); $bs->write('y'); } public function testBindingOtherStreamsMirrorsFlushOperations() { $bs = $this->_createArrayStream(''); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->flushBuffers() -> one($is2)->flushBuffers() ); $bs->bind($is1); $bs->bind($is2); $bs->flushBuffers(); } public function testUnbindingStreamPreventsFurtherWrites() { $bs = $this->_createArrayStream(''); $is1 = $this->_createMockInputStream(); $is2 = $this->_createMockInputStream(); $this->_checking(Expectations::create() -> one($is1)->write('x') -> one($is2)->write('x') -> one($is1)->write('y') ); $bs->bind($is1); $bs->bind($is2); $bs->write('x'); $bs->unbind($is2); $bs->write('y'); } // -- Creation Methods private function _createArrayStream($input) { return new Swift_ByteStream_ArrayByteStream($input); } private function _createMockInputStream() { return $this->_mock('Swift_InputByteStream'); } } Swift-4.2.1/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php100644 0 0 2672 12000050367 24225 0ustar 0 0 assertIdentical(1, $reader->getInitialByteSize()); $reader = new Swift_CharacterReader_GenericFixedWidthReader(4); $this->assertIdentical(4, $reader->getInitialByteSize()); } public function testValidationValueIsBasedOnOctetCount() { $reader = new Swift_CharacterReader_GenericFixedWidthReader(4); $this->assertIdentical( 1, $reader->validateByteSequence(array(0x01, 0x02, 0x03), 3) ); //3 octets $this->assertIdentical( 2, $reader->validateByteSequence(array(0x01, 0x0A), 2) ); //2 octets $this->assertIdentical( 3, $reader->validateByteSequence(array(0xFE), 1) ); //1 octet $this->assertIdentical( 0, $reader->validateByteSequence(array(0xFE, 0x03, 0x67, 0x9A), 4) ); //All 4 octets } public function testValidationFailsIfTooManyOctets() { $reader = new Swift_CharacterReader_GenericFixedWidthReader(6); $this->assertIdentical(-1, $reader->validateByteSequence( array(0xFE, 0x03, 0x67, 0x9A, 0x10, 0x09, 0x85), 7 )); //7 octets } } Swift-4.2.1/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php100644 0 0 2632 12000050367 22225 0ustar 0 0 read($size); ) { $c .= $bytes; $size = $v->validateCharacter($c); if (-1 == $size) { throw new Exception( ... invalid char .. ); } elseif (0 == $size) { return $c; //next character in $os } } */ private $_reader; public function setUp() { $this->_reader = new Swift_CharacterReader_UsAsciiReader(); } public function testAllValidAsciiCharactersReturnZero() { for ($ordinal = 0x00; $ordinal <= 0x7F; ++$ordinal) { $this->assertIdentical( 0, $this->_reader->validateByteSequence(array($ordinal), 1) ); } } public function testMultipleBytesAreInvalid() { for ($ordinal = 0x00; $ordinal <= 0x7F; $ordinal += 2) { $this->assertIdentical( -1, $this->_reader->validateByteSequence(array($ordinal, $ordinal + 1), 2) ); } } public function testBytesAboveAsciiRangeAreInvalid() { for ($ordinal = 0x80; $ordinal <= 0xFF; ++$ordinal) { $this->assertIdentical( -1, $this->_reader->validateByteSequence(array($ordinal), 1) ); } } } Swift-4.2.1/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php100644 0 0 3541 12000050367 21513 0ustar 0 0 _reader = new Swift_CharacterReader_Utf8Reader(); } public function testLeading7BitOctetCausesReturnZero() { for ($ordinal = 0x00; $ordinal <= 0x7F; ++$ordinal) { $this->assertIdentical( 0, $this->_reader->validateByteSequence(array($ordinal), 1) ); } } public function testLeadingByteOf2OctetCharCausesReturn1() { for ($octet = 0xC0; $octet <= 0xDF; ++$octet) { $this->assertIdentical( 1, $this->_reader->validateByteSequence(array($octet), 1) ); } } public function testLeadingByteOf3OctetCharCausesReturn2() { for ($octet = 0xE0; $octet <= 0xEF; ++$octet) { $this->assertIdentical( 2, $this->_reader->validateByteSequence(array($octet), 1) ); } } public function testLeadingByteOf4OctetCharCausesReturn3() { for ($octet = 0xF0; $octet <= 0xF7; ++$octet) { $this->assertIdentical( 3, $this->_reader->validateByteSequence(array($octet), 1) ); } } public function testLeadingByteOf5OctetCharCausesReturn4() { for ($octet = 0xF8; $octet <= 0xFB; ++$octet) { $this->assertIdentical( 4, $this->_reader->validateByteSequence(array($octet),1) ); } } public function testLeadingByteOf6OctetCharCausesReturn5() { for ($octet = 0xFC; $octet <= 0xFD; ++$octet) { $this->assertIdentical( 5, $this->_reader->validateByteSequence(array($octet),1) ); } } } Swift-4.2.1/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php100644 0 0 37676 12000050367 23702 0ustar 0 0 _getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE, 0xD1, 0x8D, 0xD0, 0xBB, 0xD0, 0xB0 ) ); } public function testCharactersWrittenUseValidator() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $stream->write(pack('C*', 0xD0, 0xBB, 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B, 0xD1, 0x85 ) ); } public function testReadCharactersAreInTact() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) //String -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) //Stream -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $stream->write(pack('C*', 0xD0, 0xBB, 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B, 0xD1, 0x85 ) ); $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1)); $this->assertIdenticalBinary( pack('C*', 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(2) ); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBB), $stream->read(1)); $this->assertIdenticalBinary( pack('C*', 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->read(3) ); $this->assertIdenticalBinary(pack('C*', 0xD1, 0x85), $stream->read(1)); $this->assertIdentical(false, $stream->read(1)); } public function testCharactersCanBeReadAsByteArrays() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) //String -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) //Stream -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD1), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $stream->write(pack('C*', 0xD0, 0xBB, 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B, 0xD1, 0x85 ) ); $this->assertEqual(array(0xD0, 0x94), $stream->readBytes(1)); $this->assertEqual(array(0xD0, 0xB6, 0xD0, 0xBE), $stream->readBytes(2)); $this->assertEqual(array(0xD0, 0xBB), $stream->readBytes(1)); $this->assertEqual( array(0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->readBytes(3) ); $this->assertEqual(array(0xD1, 0x85), $stream->readBytes(1)); $this->assertIdentical(false, $stream->readBytes(1)); } public function testRequestingLargeCharCountPastEndOfStream() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(100) ); $this->assertIdentical(false, $stream->read(1)); } public function testRequestingByteArrayCountPastEndOfStream() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $this->assertEqual(array(0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE), $stream->readBytes(100) ); $this->assertIdentical(false, $stream->readBytes(1)); } public function testPointerOffsetCanBeSet() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1)); $stream->setPointer(0); $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1)); $stream->setPointer(2); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBE), $stream->read(1)); } public function testContentsCanBeFlushed() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-sequence'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importString(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); $stream->flushContents(); $this->assertIdentical(false, $stream->read(1)); } public function testByteStreamCanBeImportingUsesValidator() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $os = $this->_getByteStream(); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-stream'); $this->_checking(Expectations::create() -> between(0,1)->of($os)->setReadPointer(0) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0x94)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xB6)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xBE)) -> ignoring($os)->read(any()) -> returns(false) ); $seq = $this->_mockery()->sequence('read-chars'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importByteStream($os); } public function testImportingStreamProducesCorrectCharArray() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $os = $this->_getByteStream(); $stream = new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'); $seq = $this->_mockery()->sequence('read-stream'); $this->_checking(Expectations::create() -> between(0,1)->of($os)->setReadPointer(0) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0x94)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xB6)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xD0)) -> one($os)->read(any()) -> inSequence($seq) -> returns(pack('C*', 0xBE)) -> ignoring($os)->read(any()) -> returns(false) ); $seq = $this->_mockery()->sequence('read-chars'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) -> one($reader)->validateByteSequence(array(0xD0), 1) -> inSequence($seq) -> returns(1) ); $stream->importByteStream($os); $this->assertIdenticalBinary(pack('C*', 0xD0, 0x94), $stream->read(1)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xB6), $stream->read(1)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBE), $stream->read(1)); $this->assertIdentical(false, $stream->read(1)); } public function testAlgorithmWithFixedWidthCharsets() { $reader = $this->_getReader(); $factory = $this->_getFactory($reader); $seq = $this->_mockery()->sequence('read-chars'); $this->_checking(Expectations::create() -> ignoring($reader)->getInitialByteSize() -> returns(2) -> one($reader)->validateByteSequence(array(0xD1, 0x8D), 2) -> inSequence($seq) -> one($reader)->validateByteSequence(array(0xD0, 0xBB), 2) -> inSequence($seq) -> one($reader)->validateByteSequence(array(0xD0, 0xB0), 2) -> inSequence($seq) ); $stream = new Swift_CharacterStream_ArrayCharacterStream( $factory, 'utf-8' ); $stream->importString(pack('C*', 0xD1, 0x8D, 0xD0, 0xBB, 0xD0, 0xB0)); $this->assertIdenticalBinary(pack('C*', 0xD1, 0x8D), $stream->read(1)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xBB), $stream->read(1)); $this->assertIdenticalBinary(pack('C*', 0xD0, 0xB0), $stream->read(1)); $this->assertIdentical(false, $stream->read(1)); } // -- Creation methods private function _getReader() { return $this->_mock('Swift_CharacterReader'); } private function _getFactory($reader) { $factory = $this->_mock('Swift_CharacterReaderFactory'); $this->_checking(Expectations::create() -> allowing($factory)->getReaderFor('utf-8') -> returns($reader) ); return $factory; } private function _getByteStream() { return $this->_mock('Swift_OutputByteStream'); } } Swift-4.2.1/tests/unit/Swift/DependencyContainerTest.php100644 0 0 14005 12000050367 20461 0ustar 0 0 arg1 = $arg1; $this->arg2 = $arg2; } } class Swift_DependencyContainerTest extends Swift_Tests_SwiftUnitTestCase { private $_container; public function setUp() { $this->_container = new Swift_DependencyContainer(); } public function testRegisterAndLookupValue() { $this->_container->register('foo')->asValue('bar'); $this->assertIdentical('bar', $this->_container->lookup('foo')); } public function testHasReturnsTrueForRegisteredValue() { $this->_container->register('foo')->asValue('bar'); $this->assertTrue($this->_container->has('foo')); } public function testHasReturnsFalseForUnregisteredValue() { $this->assertFalse($this->_container->has('foo')); } public function testRegisterAndLookupNewInstance() { $this->_container->register('one')->asNewInstanceOf('One'); $this->assertIsA($this->_container->lookup('one'), 'One'); } public function testHasReturnsTrueForRegisteredInstance() { $this->_container->register('one')->asNewInstanceOf('One'); $this->assertTrue($this->_container->has('one')); } public function testNewInstanceIsAlwaysNew() { $this->_container->register('one')->asNewInstanceOf('One'); $a = $this->_container->lookup('one'); $b = $this->_container->lookup('one'); $this->assertClone($a, $b); } public function testRegisterAndLookupSharedInstance() { $this->_container->register('one')->asSharedInstanceOf('One'); $this->assertIsA($this->_container->lookup('one'), 'One'); } public function testHasReturnsTrueForSharedInstance() { $this->_container->register('one')->asSharedInstanceOf('One'); $this->assertTrue($this->_container->has('one')); } public function testMultipleSharedInstancesAreSameInstance() { $this->_container->register('one')->asSharedInstanceOf('One'); $a = $this->_container->lookup('one'); $b = $this->_container->lookup('one'); $this->assertSame($a, $b); } public function testNewInstanceWithDependencies() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('one')->asNewInstanceOf('One') ->withDependencies(array('foo')); $obj = $this->_container->lookup('one'); $this->assertIdentical('FOO', $obj->arg1); } public function testNewInstanceWithMultipleDependencies() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('bar')->asValue(42); $this->_container->register('one')->asNewInstanceOf('One') ->withDependencies(array('foo', 'bar')); $obj = $this->_container->lookup('one'); $this->assertIdentical('FOO', $obj->arg1); $this->assertIdentical(42, $obj->arg2); } public function testNewInstanceWithInjectedObjects() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('one')->asNewInstanceOf('One'); $this->_container->register('two')->asNewInstanceOf('One') ->withDependencies(array('one', 'foo')); $obj = $this->_container->lookup('two'); $this->assertClone($this->_container->lookup('one'), $obj->arg1); $this->assertIdentical('FOO', $obj->arg2); } public function testNewInstanceWithAddConstructorValue() { $this->_container->register('one')->asNewInstanceOf('One') ->addConstructorValue('x') ->addConstructorValue(99); $obj = $this->_container->lookup('one'); $this->assertIdentical('x', $obj->arg1); $this->assertIdentical(99, $obj->arg2); } public function testNewInstanceWithAddConstructorLookup() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('bar')->asValue(42); $this->_container->register('one')->asNewInstanceOf('One') ->addConstructorLookup('foo') ->addConstructorLookup('bar'); $obj = $this->_container->lookup('one'); $this->assertIdentical('FOO', $obj->arg1); $this->assertIdentical(42, $obj->arg2); } public function testResolvedDependenciesCanBeLookedUp() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('one')->asNewInstanceOf('One'); $this->_container->register('two')->asNewInstanceOf('One') ->withDependencies(array('one', 'foo')); $deps = $this->_container->createDependenciesFor('two'); $this->assertEqual( array($this->_container->lookup('one'), 'FOO'), $deps ); } public function testArrayOfDependenciesCanBeSpecified() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('one')->asNewInstanceOf('One'); $this->_container->register('two')->asNewInstanceOf('One') ->withDependencies(array(array('one', 'foo'), 'foo')); $obj = $this->_container->lookup('two'); $this->assertEqual(array($this->_container->lookup('one'), 'FOO'), $obj->arg1); $this->assertIdentical('FOO', $obj->arg2); } public function testAliasCanBeSet() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('bar')->asAliasOf('foo'); $this->assertIdentical('FOO', $this->_container->lookup('bar')); } public function testAliasOfAliasCanBeSet() { $this->_container->register('foo')->asValue('FOO'); $this->_container->register('bar')->asAliasOf('foo'); $this->_container->register('zip')->asAliasOf('bar'); $this->_container->register('button')->asAliasOf('zip'); $this->assertIdentical('FOO', $this->_container->lookup('button')); } } Swift-4.2.1/tests/unit/Swift/Encoder/Base64EncoderTest.php100644 0 0 15006 12000050367 20445 0ustar 0 0 _encoder = new Swift_Encoder_Base64Encoder(); } /* There's really no point in testing the entire base64 encoding to the level QP encoding has been tested. base64_encode() has been in PHP for years. */ public function testInputOutputRatioIs3to4Bytes() { /* RFC 2045, 6.8 The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. */ $this->assertEqual( 'MTIz', $this->_encoder->encodeString('123'), '%s: 3 bytes of input should yield 4 bytes of output' ); $this->assertEqual( 'MTIzNDU2', $this->_encoder->encodeString('123456'), '%s: 6 bytes in input should yield 8 bytes of output' ); $this->assertEqual( 'MTIzNDU2Nzg5', $this->_encoder->encodeString('123456789'), '%s: 9 bytes in input should yield 12 bytes of output' ); } public function testPadLength() { /* RFC 2045, 6.8 Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a body. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the "=" character. Since all base64 input is an integral number of octets, only the following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ for ($i = 0; $i < 30; ++$i) { $input = pack('C', rand(0, 255)); $this->assertPattern( '~^[a-zA-Z0-9/\+]{2}==$~', $this->_encoder->encodeString($input), '%s: A single byte should have 2 bytes of padding' ); } for ($i = 0; $i < 30; ++$i) { $input = pack('C*', rand(0, 255), rand(0, 255)); $this->assertPattern( '~^[a-zA-Z0-9/\+]{3}=$~', $this->_encoder->encodeString($input), '%s: Two bytes should have 1 byte of padding' ); } for ($i = 0; $i < 30; ++$i) { $input = pack('C*', rand(0, 255), rand(0, 255), rand(0, 255)); $this->assertPattern( '~^[a-zA-Z0-9/\+]{4}$~', $this->_encoder->encodeString($input), '%s: Three bytes should have no padding' ); } } public function testMaximumLineLengthIs76Characters() { /* The encoded output stream must be represented in lines of no more than 76 characters each. All line breaks or other characters not found in Table 1 must be ignored by decoding software. */ $input = 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $output = 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk' . //38 'NERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1' . "\r\n" . //76 * 'Njc4OTBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3' . //38 'h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFla' . "\r\n" . //76 * 'MTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BRUl' . //38 'NUVVZXWFla'; //48 $this->assertEqual( $output, $this->_encoder->encodeString($input), '%s: Lines should be no more than 76 characters' ); } public function testMaximumLineLengthCanBeSpecified() { $input = 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $output = 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk' . //38 'NERUZHSElKS0' . "\r\n" . //50 * 'xNTk9QUVJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNk' . //38 'ZWZnaGlqa2xt' . "\r\n" . //50 * 'bm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1' . //38 'BRUlNUVVZXWF' . "\r\n" . //50 * 'laMTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BR' . //38 'UlNUVVZXWFla'; //50 * $this->assertEqual( $output, $this->_encoder->encodeString($input, 0, 50), '%s: Lines should be no more than 100 characters' ); } public function testFirstLineLengthCanBeDifferent() { $input = 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . '1234567890' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $output = 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk' . //38 'NERUZHSElKS0xNTk9QU' . "\r\n" . //57 * 'VJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNkZWZnaGl' . //38 'qa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLT' . "\r\n" . //76 * 'E1OT1BRUlNUVVZXWFlaMTIzNDU2Nzg5MEFCQ0R' . //38 'FRkdISUpLTE1OT1BRUlNUVVZXWFla'; //67 $this->assertEqual( $output, $this->_encoder->encodeString($input, 19), '%s: First line offset is 19 so first line should be 57 chars long' ); } } Swift-4.2.1/tests/unit/Swift/Encoder/QpEncoderTest.php100644 0 0 36256 12000050367 20013 0ustar 0 0 _createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($char) -> one($charStream)->readBytes(optional()) -> returns(array($ordinal)) -> atLeast(1)->of($charStream)->readBytes(optional()) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertIdenticalBinary($char, $encoder->encodeString($char)); } } public function testWhiteSpaceAtLineEndingIsEncoded() { /* -- RFC 2045, 6.7 -- (3) (White Space) Octets with values of 9 and 32 MAY be represented as US-ASCII TAB (HT) and SPACE characters, respectively, but MUST NOT be so represented at the end of an encoded line. Any TAB (HT) or SPACE characters on an encoded line MUST thus be followed on that line by a printable character. In particular, an "=" at the end of an encoded line, indicating a soft line break (see rule #5) may follow one or more TAB (HT) or SPACE characters. It follows that an octet with decimal value 9 or 32 appearing at the end of an encoded line must be represented according to Rule #1. This rule is necessary because some MTAs (Message Transport Agents, programs which transport messages from one user to another, or perform a portion of such transfers) are known to pad lines of text with SPACEs, and others are known to remove "white space" characters from the end of a line. Therefore, when decoding a Quoted-Printable body, any trailing white space on a line must be deleted, as it will necessarily have been added by intermediate transport agents. */ $HT = chr(0x09); //9 $SPACE = chr(0x20); //32 //HT $string = 'a' . $HT . $HT . "\r\n" . 'b'; $seq = $this->_mockery()->sequence('byte-sequence'); $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($string) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x09)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x09)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0D)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0A)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('b'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual( 'a' . $HT . '=09' . "\r\n" . 'b', $encoder->encodeString($string) ); //SPACE $string = 'a' . $SPACE . $SPACE . "\r\n" . 'b'; $seq = $this->_mockery()->sequence('byte-sequence'); $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($string) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x20)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x20)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0D)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0A)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('b'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual( 'a' . $SPACE . '=20' . "\r\n" . 'b', $encoder->encodeString($string) ); } public function testCRLFIsLeftAlone() { /* (4) (Line Breaks) A line break in a text body, represented as a CRLF sequence in the text canonical form, must be represented by a (RFC 822) line break, which is also a CRLF sequence, in the Quoted-Printable encoding. Since the canonical representation of media types other than text do not generally include the representation of line breaks as CRLF sequences, no hard line breaks (i.e. line breaks that are intended to be meaningful and to be displayed to the user) can occur in the quoted-printable encoding of such types. Sequences like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely appear in non-text data represented in quoted- printable, of course. Note that many implementations may elect to encode the local representation of various content types directly rather than converting to canonical form first, encoding, and then converting back to local representation. In particular, this may apply to plain text material on systems that use newline conventions other than a CRLF terminator sequence. Such an implementation optimization is permissible, but only when the combined canonicalization-encoding step is equivalent to performing the three steps separately. */ $string = 'a' . "\r\n" . 'b' . "\r\n" . 'c' . "\r\n"; $seq = $this->_mockery()->sequence('byte-sequence'); $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($string) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0D)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0A)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('b'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0D)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0A)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('c'))) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0D)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(0x0A)) -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual($string, $encoder->encodeString($string)); } public function testLinesLongerThan76CharactersAreSoftBroken() { /* (5) (Soft Line Breaks) The Quoted-Printable encoding REQUIRES that encoded lines be no more than 76 characters long. If longer lines are to be encoded with the Quoted-Printable encoding, "soft" line breaks must be used. An equal sign as the last character on a encoded line indicates such a non-significant ("soft") line break in the encoded text. */ $input = str_repeat('a', 140); $charStream = $this->_createCharStream(); $seq = $this->_mockery()->sequence('byte-sequence'); $exps = Expectations::create(); $exps -> one($charStream)->flushContents() -> one($charStream)->importString($input) ; $output = ''; for ($i = 0; $i < 140; ++$i) { $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))); if (75 == $i) { $output .= "=\r\n"; } $output .= 'a'; } $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false); $this->_checking($exps); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual($output, $encoder->encodeString($input)); } public function testMaxLineLengthCanBeSpecified() { $input = str_repeat('a', 100); $charStream = $this->_createCharStream(); $seq = $this->_mockery()->sequence('byte-sequence'); $exps = Expectations::create(); $exps -> one($charStream)->flushContents() -> one($charStream)->importString($input) ; $output = ''; for ($i = 0; $i < 100; ++$i) { $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))); if (53 == $i) { $output .= "=\r\n"; } $output .= 'a'; } $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false); $this->_checking($exps); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual($output, $encoder->encodeString($input, 0, 54)); } public function testBytesBelowPermittedRangeAreEncoded() { /* According to Rule (1 & 2) */ foreach (range(0, 32) as $ordinal) { $char = chr($ordinal); $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($char) -> one($charStream)->readBytes(optional()) -> returns(array($ordinal)) -> atLeast(1)->of($charStream)->readBytes(optional()) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual( sprintf('=%02X', $ordinal), $encoder->encodeString($char) ); } } public function testDecimalByte61IsEncoded() { /* According to Rule (1 & 2) */ $char = '='; $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($char) -> one($charStream)->readBytes(optional()) -> returns(array(61)) -> atLeast(1)->of($charStream)->readBytes(optional()) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual('=3D', $encoder->encodeString('=')); } public function testBytesAbovePermittedRangeAreEncoded() { /* According to Rule (1 & 2) */ foreach (range(127, 255) as $ordinal) { $char = chr($ordinal); $charStream = $this->_createCharStream(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importString($char) -> one($charStream)->readBytes(optional()) -> returns(array($ordinal)) -> atLeast(1)->of($charStream)->readBytes(optional()) -> returns(false) ); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual( sprintf('=%02X', $ordinal), $encoder->encodeString($char) ); } } public function testFirstLineLengthCanBeDifferent() { $input = str_repeat('a', 140); $charStream = $this->_createCharStream(); $seq = $this->_mockery()->sequence('byte-sequence'); $exps = Expectations::create(); $exps -> one($charStream)->flushContents(); $exps -> one($charStream)->importString($input); $output = ''; for ($i = 0; $i < 140; ++$i) { $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(array(ord('a'))); if (53 == $i || 53 + 75 == $i) { $output .= "=\r\n"; } $output .= 'a'; } $exps -> one($charStream)->readBytes(optional()) -> inSequence($seq) -> returns(false); $this->_checking($exps); $encoder = new Swift_Encoder_QpEncoder($charStream); $this->assertEqual( $output, $encoder->encodeString($input, 22), '%s: First line should start at offset 22 so can only have max length 54' ); } // -- Creation methods private function _createCharStream() { return $this->_mock('Swift_CharacterStream'); } } Swift-4.2.1/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php100644 0 0 11772 12000050367 20451 0ustar 0 0 _mock('Swift_CharacterStream'); $seq = $this->_sequence('byte-sequence'); $string = ''; foreach (range(0x00, 0x7F) as $octet) { $char = pack('C', $octet); $string .= $char; $this->_checking(Expectations::create() -> one($charStream)->read(optional()) -> inSequence($seq) -> returns($char) ); } $this->_checking(Expectations::create() -> atLeast(1)->of($charStream)->read(optional()) -> inSequence($seq) -> returns(false) -> one($charStream)->importString($string) -> ignoring($charStream)->flushContents() ); $encoder = new Swift_Encoder_Rfc2231Encoder($charStream); $encoded = $encoder->encodeString($string); foreach (explode("\r\n", $encoded) as $line) { $this->assertPattern($this->_rfc2045Token, $line, '%s: Encoder should always return a valid RFC 2045 token.'); } } public function testEncodingNonAsciiCharactersProducesValidToken() { $charStream = $this->_mock('Swift_CharacterStream'); $seq = $this->_sequence('byte-sequence'); $string = ''; foreach (range(0x80, 0xFF) as $octet) { $char = pack('C', $octet); $string .= $char; $this->_checking(Expectations::create() -> one($charStream)->read(optional()) -> inSequence($seq) -> returns($char) ); } $this->_checking(Expectations::create() -> atLeast(1)->of($charStream)->read(optional()) -> inSequence($seq) -> returns(false) -> one($charStream)->importString($string) -> ignoring($charStream)->flushContents() ); $encoder = new Swift_Encoder_Rfc2231Encoder($charStream); $encoded = $encoder->encodeString($string); foreach (explode("\r\n", $encoded) as $line) { $this->assertPattern($this->_rfc2045Token, $line, '%s: Encoder should always return a valid RFC 2045 token.'); } } public function testMaximumLineLengthCanBeSet() { $charStream = $this->_mock('Swift_CharacterStream'); $seq = $this->_sequence('byte-sequence'); $string = ''; for ($x = 0; $x < 200; ++$x) { $char = 'a'; $string .= $char; $this->_checking(Expectations::create() -> one($charStream)->read(optional()) -> inSequence($seq) -> returns($char) ); } $this->_checking(Expectations::create() -> atLeast(1)->of($charStream)->read(optional()) -> inSequence($seq) -> returns(false) -> one($charStream)->importString($string) -> ignoring($charStream)->flushContents() ); $encoder = new Swift_Encoder_Rfc2231Encoder($charStream); $encoded = $encoder->encodeString($string, 0, 75); $this->assertEqual( str_repeat('a', 75) . "\r\n" . str_repeat('a', 75) . "\r\n" . str_repeat('a', 50), $encoded, '%s: Lines should be wrapped at each 75 characters' ); } public function testFirstLineCanHaveShorterLength() { $charStream = $this->_mock('Swift_CharacterStream'); $seq = $this->_sequence('byte-sequence'); $string = ''; for ($x = 0; $x < 200; ++$x) { $char = 'a'; $string .= $char; $this->_checking(Expectations::create() -> one($charStream)->read(optional()) -> inSequence($seq) -> returns($char) ); } $this->_checking(Expectations::create() -> atLeast(1)->of($charStream)->read(optional()) -> inSequence($seq) -> returns(false) -> one($charStream)->importString($string) -> ignoring($charStream)->flushContents() ); $encoder = new Swift_Encoder_Rfc2231Encoder($charStream); $encoded = $encoder->encodeString($string, 25, 75); $this->assertEqual( str_repeat('a', 50) . "\r\n" . str_repeat('a', 75) . "\r\n" . str_repeat('a', 75), $encoded, '%s: First line should be 25 bytes shorter than the others.' ); } } Swift-4.2.1/tests/unit/Swift/Events/CommandEventTest.php100644 0 0 2272 12000050367 20347 0ustar 0 0 _createEvent($this->_createTransport(), "FOO\r\n"); $this->assertEqual("FOO\r\n", $evt->getCommand()); } public function testSuccessCodesCanBeFetchedViaGetter() { $evt = $this->_createEvent($this->_createTransport(), "FOO\r\n", array(250)); $this->assertEqual(array(250), $evt->getSuccessCodes()); } public function testSourceIsBuffer() { $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, "FOO\r\n"); $ref = $evt->getSource(); $this->assertReference($transport, $ref); } // -- Creation Methods private function _createEvent(Swift_Transport $source, $command, $successCodes = array()) { return new Swift_Events_CommandEvent($source, $command, $successCodes); } private function _createTransport() { return $this->_stub('Swift_Transport'); } } Swift-4.2.1/tests/unit/Swift/Events/EventObjectTest.php100644 0 0 1734 12000050367 20201 0ustar 0 0 _createEvent($source); $ref = $evt->getSource(); $this->assertReference($source, $ref); } public function testEventDoesNotHaveCancelledBubbleWhenNew() { $source = new stdClass(); $evt = $this->_createEvent($source); $this->assertFalse($evt->bubbleCancelled()); } public function testBubbleCanBeCancelledInEvent() { $source = new stdClass(); $evt = $this->_createEvent($source); $evt->cancelBubble(); $this->assertTrue($evt->bubbleCancelled()); } // -- Creation Methods private function _createEvent($source) { return new Swift_Events_EventObject($source); } } Swift-4.2.1/tests/unit/Swift/Events/ResponseEventTest.php100644 0 0 2463 12000050367 20571 0ustar 0 0 _createEvent($this->_createTransport(), "250 Ok\r\n", true); $this->assertEqual("250 Ok\r\n", $evt->getResponse(), '%s: Response should be available via getResponse()' ); } public function testResultCanBeFetchedViaGetter() { $evt = $this->_createEvent($this->_createTransport(), "250 Ok\r\n", false); $this->assertFalse($evt->isValid(), '%s: Result should be checkable via isValid()' ); } public function testSourceIsBuffer() { $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, "250 Ok\r\n", true); $ref = $evt->getSource(); $this->assertReference($transport, $ref); } // -- Creation Methods private function _createEvent(Swift_Transport $source, $response, $result) { return new Swift_Events_ResponseEvent($source, $response, $result); } private function _createTransport() { return $this->_stub('Swift_Transport'); } } Swift-4.2.1/tests/unit/Swift/Events/SendEventTest.php100644 0 0 6005 12000050367 17660 0ustar 0 0 _createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $ref = $evt->getMessage(); $this->assertReference($message, $ref, '%s: Message should be returned from getMessage()' ); } public function testTransportCanBeFetchViaGetter() { $message = $this->_createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $ref = $evt->getTransport(); $this->assertReference($transport, $ref, '%s: Transport should be returned from getTransport()' ); } public function testTransportCanBeFetchViaGetSource() { $message = $this->_createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $ref = $evt->getSource(); $this->assertReference($transport, $ref, '%s: Transport should be returned from getSource()' ); } public function testResultCanBeSetAndGet() { $message = $this->_createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $evt->setResult( Swift_Events_SendEvent::RESULT_SUCCESS | Swift_Events_SendEvent::RESULT_TENTATIVE ); $this->assertTrue($evt->getResult() & Swift_Events_SendEvent::RESULT_SUCCESS); $this->assertTrue($evt->getResult() & Swift_Events_SendEvent::RESULT_TENTATIVE); } public function testFailedRecipientsCanBeSetAndGet() { $message = $this->_createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $evt->setFailedRecipients(array('foo@bar', 'zip@button')); $this->assertEqual(array('foo@bar', 'zip@button'), $evt->getFailedRecipients(), '%s: FailedRecipients should be returned from getter' ); } public function testFailedRecipientsGetsPickedUpCorrectly() { $message = $this->_createMessage(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $message); $this->assertEqual(array(), $evt->getFailedRecipients()); } // -- Creation Methods private function _createEvent(Swift_Transport $source, Swift_Mime_Message $message) { return new Swift_Events_SendEvent($source, $message); } private function _createTransport() { return $this->_stub('Swift_Transport'); } private function _createMessage() { return $this->_stub('Swift_Mime_Message'); } } Swift-4.2.1/tests/unit/Swift/Events/SimpleEventDispatcherTest.php100644 0 0 13355 12000050367 22255 0ustar 0 0 _dispatcher = new Swift_Events_SimpleEventDispatcher(); } public function testSendEventCanBeCreated() { $transport = $this->_stub('Swift_Transport'); $message = $this->_stub('Swift_Mime_Message'); $evt = $this->_dispatcher->createSendEvent($transport, $message); $this->assertIsA($evt, 'Swift_Events_SendEvent'); $this->assertSame($message, $evt->getMessage()); $this->assertSame($transport, $evt->getTransport()); } public function testCommandEventCanBeCreated() { $buf = $this->_stub('Swift_Transport'); $evt = $this->_dispatcher->createCommandEvent($buf, "FOO\r\n", array(250)); $this->assertIsA($evt, 'Swift_Events_CommandEvent'); $this->assertSame($buf, $evt->getSource()); $this->assertEqual("FOO\r\n", $evt->getCommand()); $this->assertEqual(array(250), $evt->getSuccessCodes()); } public function testResponseEventCanBeCreated() { $buf = $this->_stub('Swift_Transport'); $evt = $this->_dispatcher->createResponseEvent($buf, "250 Ok\r\n", true); $this->assertIsA($evt, 'Swift_Events_ResponseEvent'); $this->assertSame($buf, $evt->getSource()); $this->assertEqual("250 Ok\r\n", $evt->getResponse()); $this->assertTrue($evt->isValid()); } public function testTransportChangeEventCanBeCreated() { $transport = $this->_stub('Swift_Transport'); $evt = $this->_dispatcher->createTransportChangeEvent($transport); $this->assertIsA($evt, 'Swift_Events_TransportChangeEvent'); $this->assertSame($transport, $evt->getSource()); } public function testTransportExceptionEventCanBeCreated() { $transport = $this->_stub('Swift_Transport'); $ex = new Swift_TransportException(''); $evt = $this->_dispatcher->createTransportExceptionEvent($transport, $ex); $this->assertIsA($evt, 'Swift_Events_TransportExceptionEvent'); $this->assertSame($transport, $evt->getSource()); $this->assertSame($ex, $evt->getException()); } public function testListenersAreNotifiedOfDispatchedEvent() { $transport = $this->_stub('Swift_Transport'); $evt = $this->_dispatcher->createTransportChangeEvent($transport); $listenerA = $this->_mock('Swift_Events_TransportChangeListener'); $listenerB = $this->_mock('Swift_Events_TransportChangeListener'); $this->_dispatcher->bindEventListener($listenerA); $this->_dispatcher->bindEventListener($listenerB); $this->_checking(Expectations::create() -> one($listenerA)->transportStarted($evt) -> one($listenerB)->transportStarted($evt) ); $this->_dispatcher->dispatchEvent($evt, 'transportStarted'); } public function testListenersAreOnlyCalledIfImplementingCorrectInterface() { $transport = $this->_stub('Swift_Transport'); $message = $this->_stub('Swift_Mime_Message'); $evt = $this->_dispatcher->createSendEvent($transport, $message); $targetListener = $this->_mock('Swift_Events_SendListener'); $otherListener = $this->_mock('Swift_Events_TransportChangeListener'); $this->_dispatcher->bindEventListener($targetListener); $this->_dispatcher->bindEventListener($otherListener); $this->_checking(Expectations::create() -> one($targetListener)->sendPerformed($evt) -> never($otherListener) ); $this->_dispatcher->dispatchEvent($evt, 'sendPerformed'); } public function testListenersCanCancelBubblingOfEvent() { $transport = $this->_stub('Swift_Transport'); $message = $this->_stub('Swift_Mime_Message'); $evt = $this->_dispatcher->createSendEvent($transport, $message); $listenerA = $this->_mock('Swift_Events_SendListener'); $listenerB = $this->_mock('Swift_Events_SendListener'); $this->_dispatcher->bindEventListener($listenerA); $this->_dispatcher->bindEventListener($listenerB); $this->_checking(Expectations::create() -> one($listenerA)->sendPerformed($evt) -> calls(array($this, '_cancelBubble')) -> never($listenerB) ); $this->_dispatcher->dispatchEvent($evt, 'sendPerformed'); $this->assertTrue($evt->bubbleCancelled()); } public function testAddingListenerTwiceDoesNotReceiveEventTwice() { $transport = $this->_stub('Swift_Transport'); $evt = $this->_dispatcher->createTransportChangeEvent($transport); $listener = $this->_mock('Swift_Events_TransportChangeListener'); $this->_dispatcher->bindEventListener($listener); $this->_dispatcher->bindEventListener($listener); $this->_checking(Expectations::create() -> one($listener)->transportStarted($evt) -> never($listener)->transportStarted($evt) ); $this->_dispatcher->dispatchEvent($evt, 'transportStarted'); } // -- Mock callbacks public function _cancelBubble(Yay_Invocation $inv) { $args = $inv->getArguments(); $args[0]->cancelBubble(true); } // -- Private methods private function _createDispatcher(array $map) { $dispatcher = new Swift_Events_SimpleEventDispatcher($map); return $dispatcher; } } Swift-4.2.1/tests/unit/Swift/Events/TransportChangeEventTest.php100644 0 0 1731 12000050367 22072 0ustar 0 0 _createTransport(); $evt = $this->_createEvent($transport); $ref = $evt->getTransport(); $this->assertReference($transport, $ref); } public function testSourceIsTransport() { $transport = $this->_createTransport(); $evt = $this->_createEvent($transport); $ref = $evt->getSource(); $this->assertReference($transport, $ref); } // -- Creation Methods private function _createEvent(Swift_Transport $source) { return new Swift_Events_TransportChangeEvent($source); } private function _createTransport() { return $this->_stub('Swift_Transport'); } } Swift-4.2.1/tests/unit/Swift/Events/TransportExceptionEventTest.php100644 0 0 2632 12000050367 22644 0ustar 0 0 _createException(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $ex); $ref = $evt->getException(); $this->assertReference($ex, $ref, '%s: Exception should be available via getException()' ); } public function testSourceIsTransport() { $ex = $this->_createException(); $transport = $this->_createTransport(); $evt = $this->_createEvent($transport, $ex); $ref = $evt->getSource(); $this->assertReference($transport, $ref, '%s: Transport should be available via getSource()' ); } // -- Creation Methods private function _createEvent(Swift_Transport $transport, Swift_TransportException $ex) { return new Swift_Events_TransportExceptionEvent($transport, $ex); } private function _createTransport() { return $this->_stub('Swift_Transport'); } private function _createException() { return new Swift_TransportException(''); } } Swift-4.2.1/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php100644 0 0 17667 12000050367 20710 0ustar 0 0 _createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeOverwritten() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->setString( $this->_key1, 'foo', 'whatever', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('whatever', $cache->getString($this->_key1, 'foo')); } public function testStringDataCanBeAppended() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->setString( $this->_key1, 'foo', 'ing', Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testing', $cache->getString($this->_key1, 'foo')); } public function testHasKeyReturnValue() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($cache->hasKey($this->_key1, 'foo')); } public function testNsKeyIsWellPartitioned() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->setString( $this->_key2, 'foo', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $cache->getString($this->_key2, 'foo')); } public function testItemKeyIsWellPartitioned() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->setString( $this->_key1, 'bar', 'ing', Swift_KeyCache::MODE_WRITE ); $this->assertEqual('test', $cache->getString($this->_key1, 'foo')); $this->assertEqual('ing', $cache->getString($this->_key1, 'bar')); } public function testByteStreamCanBeImported() { $os = $this->_createOutputStream(); $this->_checking(Expectations::create() -> one($os)->read(optional()) -> returns('abc') -> one($os)->read(optional()) -> returns('def') -> one($os)->read(optional()) -> returns(false) -> ignoring($os) ); $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_WRITE ); $this->assertEqual('abcdef', $cache->getString($this->_key1, 'foo')); } public function testByteStreamCanBeAppended() { $os1 = $this->_createOutputStream(); $os2 = $this->_createOutputStream(); $this->_checking(Expectations::create() -> one($os1)->read(optional()) -> returns('abc') -> one($os1)->read(optional()) -> returns('def') -> one($os1)->read(optional()) -> returns(false) -> ignoring($os1) -> one($os2)->read(optional()) -> returns('xyz') -> one($os2)->read(optional()) -> returns('uvw') -> one($os2)->read(optional()) -> returns(false) -> ignoring($os2) ); $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->importFromByteStream( $this->_key1, 'foo', $os1, Swift_KeyCache::MODE_APPEND ); $cache->importFromByteStream( $this->_key1, 'foo', $os2, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('abcdefxyzuvw', $cache->getString($this->_key1, 'foo')); } public function testByteStreamAndStringCanBeAppended() { $os = $this->_createOutputStream(); $this->_checking(Expectations::create() -> one($os)->read(optional()) -> returns('abc') -> one($os)->read(optional()) -> returns('def') -> one($os)->read(optional()) -> returns(false) -> ignoring($os) ); $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_APPEND ); $cache->importFromByteStream( $this->_key1, 'foo', $os, Swift_KeyCache::MODE_APPEND ); $this->assertEqual('testabcdef', $cache->getString($this->_key1, 'foo')); } public function testDataCanBeExportedToByteStream() { //See acceptance test for more detail $is = $this->_createInputStream(); $this->_checking(Expectations::create() -> atLeast(1)->of($is)->write(any()) -> ignoring($is) ); $kcis = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($kcis); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->exportToByteStream($this->_key1, 'foo', $is); } public function testKeyCanBeCleared() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($cache->hasKey($this->_key1, 'foo')); $cache->clearKey($this->_key1, 'foo'); $this->assertFalse($cache->hasKey($this->_key1, 'foo')); } public function testNsKeyCanBeCleared() { $is = $this->_createKeyCacheInputStream(true); $cache = $this->_createCache($is); $cache->setString( $this->_key1, 'foo', 'test', Swift_KeyCache::MODE_WRITE ); $cache->setString( $this->_key1, 'bar', 'xyz', Swift_KeyCache::MODE_WRITE ); $this->assertTrue($cache->hasKey($this->_key1, 'foo')); $this->assertTrue($cache->hasKey($this->_key1, 'bar')); $cache->clearAll($this->_key1); $this->assertFalse($cache->hasKey($this->_key1, 'foo')); $this->assertFalse($cache->hasKey($this->_key1, 'bar')); } // -- Creation methods private function _createCache($is) { return new Swift_KeyCache_ArrayKeyCache($is); } private function _createKeyCacheInputStream($stub = false) { return $stub ? $this->_stub('Swift_KeyCache_KeyCacheInputStream') : $this->_mock('Swift_KeyCache_KeyCacheInputStream') ; } private function _createOutputStream($stub = false) { return $stub ? $this->_stub('Swift_OutputByteStream') : $this->_mock('Swift_OutputByteStream') ; } private function _createInputStream($stub = false) { return $stub ? $this->_stub('Swift_InputByteStream') : $this->_mock('Swift_InputByteStream') ; } } Swift-4.2.1/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php100644 0 0 4643 12000050367 23225 0ustar 0 0 _createKeyCache(); $this->_checking(Expectations::create() -> one($cache)->setString($this->_nsKey, 'foo', 'a', Swift_KeyCache::MODE_APPEND) -> one($cache)->setString($this->_nsKey, 'foo', 'b', Swift_KeyCache::MODE_APPEND) -> one($cache)->setString($this->_nsKey, 'foo', 'c', Swift_KeyCache::MODE_APPEND) ); $stream = new Swift_KeyCache_SimpleKeyCacheInputStream(); $stream->setKeyCache($cache); $stream->setNsKey($this->_nsKey); $stream->setItemKey('foo'); $stream->write('a'); $stream->write('b'); $stream->write('c'); } public function testFlushContentClearsKey() { $cache = $this->_createKeyCache(); $this->_checking(Expectations::create() -> one($cache)->clearKey($this->_nsKey, 'foo') ); $stream = new Swift_KeyCache_SimpleKeyCacheInputStream(); $stream->setKeyCache($cache); $stream->setNsKey($this->_nsKey); $stream->setItemKey('foo'); $stream->flushBuffers(); } public function testClonedStreamStillReferencesSameCache() { $cache = $this->_createKeyCache(); $this->_checking(Expectations::create() -> one($cache)->setString($this->_nsKey, 'foo', 'a', Swift_KeyCache::MODE_APPEND) -> one($cache)->setString($this->_nsKey, 'foo', 'b', Swift_KeyCache::MODE_APPEND) -> one($cache)->setString('test', 'bar', 'x', Swift_KeyCache::MODE_APPEND) ); $stream = new Swift_KeyCache_SimpleKeyCacheInputStream(); $stream->setKeyCache($cache); $stream->setNsKey($this->_nsKey); $stream->setItemKey('foo'); $stream->write('a'); $stream->write('b'); $newStream = clone $stream; $newStream->setKeyCache($cache); $newStream->setNsKey('test'); $newStream->setItemKey('bar'); $newStream->write('x'); } // -- Creation Methods private function _createKeyCache() { return $this->_mock('Swift_KeyCache'); } } Swift-4.2.1/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php100644 0 0 3074 12000050367 22370 0ustar 0 0 assertFalse($it->hasNext()); } public function testHasNextReturnsTrueIfItemsLeft() { $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo')); $this->assertTrue($it->hasNext()); } public function testReadingToEndOfListCausesHasNextToReturnFalse() { $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo')); $this->assertTrue($it->hasNext()); $it->nextRecipient(); $this->assertFalse($it->hasNext()); } public function testReturnedValueHasPreservedKeyValuePair() { $it = new Swift_Mailer_ArrayRecipientIterator(array('foo@bar' => 'Foo')); $this->assertEqual(array('foo@bar' => 'Foo'), $it->nextRecipient()); } public function testIteratorMovesNextAfterEachIteration() { $it = new Swift_Mailer_ArrayRecipientIterator(array( 'foo@bar' => 'Foo', 'zip@button' => 'Zip thing', 'test@test' => null )); $this->assertEqual(array('foo@bar' => 'Foo'), $it->nextRecipient()); $this->assertEqual(array('zip@button' => 'Zip thing'), $it->nextRecipient()); $this->assertEqual(array('test@test' => null), $it->nextRecipient()); } } Swift-4.2.1/tests/unit/Swift/MailerTest.php100644 0 0 12040 12000050367 15746 0ustar 0 0 _createTransport(); $message = $this->_createMessage(); $con = $this->_states('Connection')->startsAs('off'); $this->_checking(Expectations::create() -> allowing($transport)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($transport)->isStarted() -> returns(false) -> when($con->is('on')) -> one($transport)->start() -> when($con->is('off')) -> then($con->is('on')) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); $mailer->send($message); } public function testTransportIsOnlyStartedOnce() { $transport = $this->_createTransport(); $message = $this->_createMessage(); $con = $this->_states('Connection')->startsAs('off'); $this->_checking(Expectations::create() -> allowing($transport)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($transport)->isStarted() -> returns(false) -> when($con->is('on')) -> one($transport)->start() -> when($con->is('off')) -> then($con->is('on')) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); for ($i = 0; $i < 10; ++$i) { $mailer->send($message); } } public function testMessageIsPassedToTransport() { $transport = $this->_createTransport(); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($transport)->send($message, optional()) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); $mailer->send($message); } public function testSendReturnsCountFromTransport() { $transport = $this->_createTransport(); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($transport)->send($message, optional()) -> returns(57) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); $this->assertEqual(57, $mailer->send($message)); } public function testFailedRecipientReferenceIsPassedToTransport() { $failures = array(); $transport = $this->_createTransport(); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($transport)->send($message, reference($failures)) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); $mailer->send($message, $failures); } public function testSendRecordsRfcComplianceExceptionAsEntireSendFailure() { $failures = array(); $rfcException = new Swift_RfcComplianceException('test'); $transport = $this->_createTransport(); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo&invalid' => 'Foo', 'bar@valid.tld' => 'Bar')) -> one($transport)->send($message, reference($failures)) -> throws($rfcException) -> ignoring($transport) -> ignoring($message) ); $mailer = $this->_createMailer($transport); $this->assertEqual(0, $mailer->send($message, $failures), '%s: Should return 0'); $this->assertEqual(array('foo&invalid', 'bar@valid.tld'), $failures, '%s: Failures should contain all addresses since the entire message failed to compile'); } public function testRegisterPluginDelegatesToTransport() { $plugin = $this->_createPlugin(); $transport = $this->_createTransport(); $mailer = $this->_createMailer($transport); $this->_checking(Expectations::create() -> one($transport)->registerPlugin($plugin) ); $mailer->registerPlugin($plugin); } // -- Creation methods private function _createPlugin() { return $this->_mock('Swift_Events_EventListener'); } private function _createTransport() { return $this->_mock('Swift_Transport'); } private function _createMessage() { return $this->_mock('Swift_Mime_Message'); } private function _createIterator() { return $this->_mock('Swift_Mailer_RecipientIterator'); } private function _createMailer(Swift_Transport $transport) { return new Swift_Mailer($transport); } } Swift-4.2.1/tests/unit/Swift/Mime/AbstractMimeEntityTest.php100644 0 0 112025 12000050367 21220 0ustar 0 0 _createHeaderSet(); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $this->assertSame($headers, $entity->getHeaders()); } public function testContentTypeIsReturnedFromHeader() { $ctype = $this->_createHeader('Content-Type', 'image/jpeg-test'); $headers = $this->_createHeaderSet(array('Content-Type' => $ctype)); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('image/jpeg-test', $entity->getContentType()); } public function testContentTypeIsSetInHeader() { $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false); $headers = $this->_createHeaderSet(array('Content-Type' => $ctype)); $this->_checking(Expectations::create() -> one($ctype)->setFieldBodyModel('image/jpeg') -> ignoring($ctype) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setContentType('image/jpeg'); } public function testContentTypeHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addParameterizedHeader('Content-Type', 'image/jpeg') -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setContentType('image/jpeg'); } public function testContentTypeCanBeSetViaSetBody() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addParameterizedHeader('Content-Type', 'text/html') -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBody('foo', 'text/html'); } public function testGetEncoderFromConstructor() { $encoder = $this->_createEncoder('base64'); $entity = $this->_createEntity($this->_createHeaderSet(), $encoder, $this->_createCache() ); $this->assertSame($encoder, $entity->getEncoder()); } public function testSetAndGetEncoder() { $encoder = $this->_createEncoder('base64'); $headers = $this->_createHeaderSet(); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setEncoder($encoder); $this->assertSame($encoder, $entity->getEncoder()); } public function testSettingEncoderUpdatesTransferEncoding() { $encoder = $this->_createEncoder('base64'); $encoding = $this->_createHeader( 'Content-Transfer-Encoding', '8bit', array(), false ); $headers = $this->_createHeaderSet(array( 'Content-Transfer-Encoding' => $encoding )); $this->_checking(Expectations::create() -> one($encoding)->setFieldBodyModel('base64') -> ignoring($encoding) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setEncoder($encoder); } public function testSettingEncoderAddsEncodingHeaderIfNonePresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addTextHeader('Content-Transfer-Encoding', 'something') -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setEncoder($this->_createEncoder('something')); } public function testIdIsReturnedFromHeader() { /* -- RFC 2045, 7. In constructing a high-level user agent, it may be desirable to allow one body to make reference to another. Accordingly, bodies may be labelled using the "Content-ID" header field, which is syntactically identical to the "Message-ID" header field */ $cid = $this->_createHeader('Content-ID', 'zip@button'); $headers = $this->_createHeaderSet(array('Content-ID' => $cid)); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('zip@button', $entity->getId()); } public function testIdIsSetInHeader() { $cid = $this->_createHeader('Content-ID', 'zip@button', array(), false); $headers = $this->_createHeaderSet(array('Content-ID' => $cid)); $this->_checking(Expectations::create() -> one($cid)->setFieldBodyModel('foo@bar') -> ignoring($cid) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setId('foo@bar'); } public function testIdIsAutoGenerated() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertPattern('/^.*?@.*?$/D', $entity->getId()); } public function testGenerateIdCreatesNewId() { $headers = $this->_createHeaderSet(); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $id1 = $entity->generateId(); $id2 = $entity->generateId(); $this->assertNotEqual($id1, $id2); } public function testGenerateIdSetsNewId() { $headers = $this->_createHeaderSet(); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $id = $entity->generateId(); $this->assertEqual($id, $entity->getId()); } public function testDescriptionIsReadFromHeader() { /* -- RFC 2045, 8. The ability to associate some descriptive information with a given body is often desirable. For example, it may be useful to mark an "image" body as "a picture of the Space Shuttle Endeavor." Such text may be placed in the Content-Description header field. This header field is always optional. */ $desc = $this->_createHeader('Content-Description', 'something'); $headers = $this->_createHeaderSet(array('Content-Description' => $desc)); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('something', $entity->getDescription()); } public function testDescriptionIsSetInHeader() { $desc = $this->_createHeader('Content-Description', '', array(), false); $headers = $this->_createHeaderSet(array('Content-Description' => $desc)); $this->_checking(Expectations::create() -> one($desc)->setFieldBodyModel('whatever') -> ignoring($desc) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setDescription('whatever'); } public function testDescriptionHeaderIsAddedIfNotPresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addTextHeader('Content-Description', 'whatever') -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setDescription('whatever'); } public function testSetAndGetMaxLineLength() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setMaxLineLength(60); $this->assertEqual(60, $entity->getMaxLineLength()); } public function testEncoderIsUsedForStringGeneration() { $encoder = $this->_createEncoder('base64', false); $this->_checking(Expectations::create() -> one($encoder)->encodeString('blah', optional()) -> ignoring($encoder) ); $entity = $this->_createEntity($this->_createHeaderSet(), $encoder, $this->_createCache() ); $entity->setBody("blah"); $entity->toString(); } public function testMaxLineLengthIsProvidedWhenEncoding() { $encoder = $this->_createEncoder('base64', false); $this->_checking(Expectations::create() -> one($encoder)->encodeString('blah', 0, 65) -> ignoring($encoder) ); $entity = $this->_createEntity($this->_createHeaderSet(), $encoder, $this->_createCache() ); $entity->setBody("blah"); $entity->setMaxLineLength(65); $entity->toString(); } public function testHeadersAppearInString() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" . "X-MyHeader: foobar\r\n" ) -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $this->assertEqual( "Content-Type: text/plain; charset=utf-8\r\n" . "X-MyHeader: foobar\r\n", $entity->toString() ); } public function testSetAndGetBody() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setBody("blah\r\nblah!"); $this->assertEqual("blah\r\nblah!", $entity->getBody()); } public function testBodyIsAppended() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBody("blah\r\nblah!"); $this->assertEqual( "Content-Type: text/plain; charset=utf-8\r\n" . "\r\n" . "blah\r\nblah!", $entity->toString() ); } public function testGetBodyReturnsStringFromByteStream() { $os = $this->_createOutputStream("byte stream string"); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setBody($os); $this->assertEqual("byte stream string", $entity->getBody()); } public function testByteStreamBodyIsAppended() { $headers = $this->_createHeaderSet(array(), false); $os = $this->_createOutputStream("streamed"); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBody($os); $this->assertEqual( "Content-Type: text/plain; charset=utf-8\r\n" . "\r\n" . "streamed", $entity->toString() ); } public function testBoundaryCanBeRetrieved() { /* -- RFC 2046, 5.1.1. boundary := 0*69 bcharsnospace bchars := bcharsnospace / " " bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?" */ $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertPattern( '/^[a-zA-Z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-zA-Z0-9\'\(\)\+_\-,\.\/:=\?]$/D', $entity->getBoundary() ); } public function testBoundaryNeverChanges() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $firstBoundary = $entity->getBoundary(); for ($i = 0; $i < 10; $i++) { $this->assertEqual($firstBoundary, $entity->getBoundary()); } } public function testBoundaryCanBeSet() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setBoundary('foobar'); $this->assertEqual('foobar', $entity->getBoundary()); } public function testAddingChildrenGeneratesBoundaryInHeaders() { $child = $this->_createChild(); $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false); $this->_checking(Expectations::create() -> one($cType)->setParameter('boundary', any()) -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType )), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); } public function testChildrenOfLevelAttachmentAndLessCauseMultipartMixed() { for ($level = Swift_Mime_MimeEntity::LEVEL_MIXED; $level > Swift_Mime_MimeEntity::LEVEL_TOP; $level /= 2) { $child = $this->_createChild($level); $cType = $this->_createHeader( 'Content-Type', 'text/plain', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel('multipart/mixed') -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); } } public function testChildrenOfLevelAlternativeAndLessCauseMultipartAlternative() { for ($level = Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE; $level > Swift_Mime_MimeEntity::LEVEL_MIXED; $level /= 2) { $child = $this->_createChild($level); $cType = $this->_createHeader( 'Content-Type', 'text/plain', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel('multipart/alternative') -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); } } public function testChildrenOfLevelRelatedAndLessCauseMultipartRelated() { for ($level = Swift_Mime_MimeEntity::LEVEL_RELATED; $level > Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE; $level /= 2) { $child = $this->_createChild($level); $cType = $this->_createHeader( 'Content-Type', 'text/plain', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel('multipart/related') -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); } } public function testHighestLevelChildDeterminesContentType() { $combinations = array( array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED, Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, Swift_Mime_MimeEntity::LEVEL_RELATED ), 'type' => 'multipart/mixed' ), array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED, Swift_Mime_MimeEntity::LEVEL_RELATED ), 'type' => 'multipart/mixed' ), array('levels' => array(Swift_Mime_MimeEntity::LEVEL_MIXED, Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE ), 'type' => 'multipart/mixed' ), array('levels' => array(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, Swift_Mime_MimeEntity::LEVEL_RELATED ), 'type' => 'multipart/alternative' ) ); foreach ($combinations as $combination) { $children = array(); foreach ($combination['levels'] as $level) { $children[] = $this->_createChild($level); } $cType = $this->_createHeader( 'Content-Type', 'text/plain', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel($combination['type']) -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren($children); } } public function testChildrenAppearNestedInString() { /* -- RFC 2046, 5.1.1. (excerpt too verbose to paste here) */ $headers = $this->_createHeaderSet(array(), false); $child1 = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, "Content-Type: text/plain\r\n" . "\r\n" . "foobar" ); $child2 = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, "Content-Type: text/html\r\n" . "\r\n" . "foobar" ); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n" ) -> ignoring($headers) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBoundary('xxx'); $entity->setChildren(array($child1, $child2)); $this->assertEqual( "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n" . "\r\n" . "\r\n--xxx\r\n" . "Content-Type: text/plain\r\n" . "\r\n" . "foobar\r\n" . "\r\n--xxx\r\n" . "Content-Type: text/html\r\n" . "\r\n" . "foobar\r\n" . "\r\n--xxx--\r\n", $entity->toString() ); } public function testMixingLevelsIsHierarchical() { $headers = $this->_createHeaderSet(array(), false); $newHeaders = $this->_createHeaderSet(array(), false); $part = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, "Content-Type: text/plain\r\n" . "\r\n" . "foobar" ); $attachment = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_MIXED, "Content-Type: application/octet-stream\r\n" . "\r\n" . "data" ); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: multipart/mixed; boundary=\"xxx\"\r\n" ) -> ignoring($headers)->newInstance() -> returns($newHeaders) -> ignoring($headers) -> ignoring($newHeaders)->toString() -> returns( "Content-Type: multipart/alternative; boundary=\"yyy\"\r\n" ) -> ignoring($newHeaders) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBoundary('xxx'); $entity->setChildren(array($part, $attachment)); $this->assertPattern( "~^" . "Content-Type: multipart/mixed; boundary=\"xxx\"\r\n" . "\r\n\r\n--xxx\r\n" . "Content-Type: multipart/alternative; boundary=\"yyy\"\r\n" . "\r\n\r\n--(.*?)\r\n" . "Content-Type: text/plain\r\n" . "\r\n" . "foobar" . "\r\n\r\n--\\1--\r\n" . "\r\n\r\n--xxx\r\n" . "Content-Type: application/octet-stream\r\n" . "\r\n" . "data" . "\r\n\r\n--xxx--\r\n" . "\$~", $entity->toString() ); } public function testSettingEncoderNotifiesChildren() { $child = $this->_createChild(0, '', false); $encoder = $this->_createEncoder('base64'); $this->_checking(Expectations::create() -> one($child)->encoderChanged($encoder) -> ignoring($child) ); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); $entity->setEncoder($encoder); } public function testReceiptOfEncoderChangeNotifiesChildren() { $child = $this->_createChild(0, '', false); $encoder = $this->_createEncoder('base64'); $this->_checking(Expectations::create() -> one($child)->encoderChanged($encoder) -> ignoring($child) ); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); $entity->encoderChanged($encoder); } public function testReceiptOfCharsetChangeNotifiesChildren() { $child = $this->_createChild(0, '', false); $this->_checking(Expectations::create() -> one($child)->charsetChanged('windows-874') -> ignoring($child) ); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $entity->setChildren(array($child)); $entity->charsetChanged('windows-874'); } public function testEntityIsWrittenToByteStream() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $is = $this->_createInputStream(false); $this->_checking(Expectations::create() -> atLeast(1)->of($is)->write(any()) -> ignoring($is) ); $entity->toByteStream($is); } public function testEntityHeadersAreComittedToByteStream() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $is = $this->_createInputStream(false); $this->_checking(Expectations::create() -> atLeast(1)->of($is)->commit() -> atLeast(1)->of($is)->write(any()) -> ignoring($is) ); $entity->toByteStream($is); } public function testOrderingTextBeforeHtml() { $htmlChild = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, "Content-Type: text/html\r\n" . "\r\n" . "HTML PART", false ); $textChild = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, "Content-Type: text/plain\r\n" . "\r\n" . "TEXT PART", false ); $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n" ) -> ignoring($headers) -> ignoring($htmlChild)->getContentType() -> returns('text/html') -> ignoring($htmlChild) -> ignoring($textChild)->getContentType() -> returns('text/plain') -> ignoring($textChild) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $this->_createCache() ); $entity->setBoundary('xxx'); $entity->setChildren(array($htmlChild, $textChild)); $this->assertEqual( "Content-Type: multipart/alternative; boundary=\"xxx\"\r\n" . "\r\n\r\n--xxx\r\n" . "Content-Type: text/plain\r\n" . "\r\n" . "TEXT PART" . "\r\n\r\n--xxx\r\n" . "Content-Type: text/html\r\n" . "\r\n" . "HTML PART" . "\r\n\r\n--xxx--\r\n", $entity->toString() ); } public function testUnsettingChildrenRestoresContentType() { $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false); $child = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE); $s = $this->_mockery()->sequence('Type setting'); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel('image/jpeg') -> inSequence($s) -> one($cType)->setFieldBodyModel('multipart/alternative') -> inSequence($s) -> one($cType)->setFieldBodyModel('image/jpeg') -> inSequence($s) -> ignoring($cType) ); $entity = $this->_createEntity($this->_createHeaderSet(array( 'Content-Type' => $cType )), $this->_createEncoder(), $this->_createCache() ); $entity->setContentType('image/jpeg'); $entity->setChildren(array($child)); $entity->setChildren(array()); } public function testBodyIsReadFromCacheWhenUsingToStringIfPresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->hasKey(any(), 'body') -> returns(true) -> one($cache)->getString(any(), 'body') -> returns("\r\ncache\r\ncache!") -> ignoring($cache) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $this->assertEqual( "Content-Type: text/plain; charset=utf-8\r\n" . "\r\n" . "cache\r\ncache!", $entity->toString() ); } public function testBodyIsAddedToCacheWhenUsingToString() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->hasKey(any(), 'body') -> returns(false) -> one($cache)->setString(any(), 'body', "\r\nblah\r\nblah!", Swift_KeyCache::MODE_WRITE) -> ignoring($cache) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $entity->toString(); } public function testBodyIsClearedFromCacheIfNewBodySet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->clearKey(any(), 'body') -> ignoring($cache) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $entity->toString(); $entity->setBody("new\r\nnew!"); } public function testBodyIsNotClearedFromCacheIfSameBodySet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> never($cache)->clearKey(any(), 'body') -> ignoring($cache) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $entity->toString(); $entity->setBody("blah\r\nblah!"); } public function testBodyIsClearedFromCacheIfNewEncoderSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->clearKey(any(), 'body') -> ignoring($cache) ); $otherEncoder = $this->_createEncoder(); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $entity->toString(); $entity->setEncoder($otherEncoder); } public function testBodyIsReadFromCacheWhenUsingToByteStreamIfPresent() { $is = $this->_createInputStream(); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->hasKey(any(), 'body') -> returns(true) -> one($cache)->exportToByteStream(any(), 'body', $is) -> ignoring($cache) ); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $cache ); $entity->setBody('foo'); $entity->toByteStream($is); } public function testBodyIsAddedToCacheWhenUsingToByteStream() { $is = $this->_createInputStream(); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->hasKey(any(), 'body') -> returns(false) //The input stream should be fetched for writing // Proving that it's actually written to is possible, but extremely // fragile. Best let the acceptance tests cover this aspect -> one($cache)->getInputByteStream(any(), 'body') -> ignoring($cache) ); $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $cache ); $entity->setBody('foo'); $entity->toByteStream($is); } public function testFluidInterface() { $entity = $this->_createEntity($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertSame($entity, $entity ->setContentType('text/plain') ->setEncoder($this->_createEncoder()) ->setId('foo@bar') ->setDescription('my description') ->setMaxLineLength(998) ->setBody('xx') ->setBoundary('xyz') ->setChildren(array()) ); } // -- Private helpers abstract protected function _createEntity($headers, $encoder, $cache); protected function _createChild($level = null, $string = '', $stub = true) { $child = $this->_mock('Swift_Mime_MimeEntity'); if (isset($level)) { $this->_checking(Expectations::create() -> ignoring($child)->getNestingLevel() -> returns($level) ); } $this->_checking(Expectations::create() -> ignoring($child)->toString() -> returns($string) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($child) ); } return $child; } protected function _createEncoder($name = 'quoted-printable', $stub = true) { $encoder = $this->_mock('Swift_Mime_ContentEncoder'); $this->_checking(Expectations::create() -> ignoring($encoder)->getName() -> returns($name) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($encoder)->encodeString(any(), optional()) -> calls(array($this, 'returnStringFromEncoder')) -> ignoring($encoder) ); } return $encoder; } protected function _createCache($stub = true) { $cache = $this->_mock('Swift_KeyCache'); if ($stub) { $this->_checking(Expectations::create() -> ignoring($cache) ); } return $cache; } protected function _createHeaderSet($headers = array(), $stub = true) { $set = $this->_mock('Swift_Mime_HeaderSet'); foreach ($headers as $key => $header) { $this->_checking(Expectations::create() -> ignoring($set)->has($key) -> returns(true) -> ignoring($set)->get($key) -> returns($header) ); } if ($stub) { $this->_checking(Expectations::create() -> ignoring($set)->newInstance() -> returns($set) -> ignoring($set) ); } return $set; } protected function _createHeader($name, $model = null, $params = array(), $stub = true) { $header = $this->_mock('Swift_Mime_ParameterizedHeader'); $this->_checking(Expectations::create() -> ignoring($header)->getFieldName() -> returns($name) -> ignoring($header)->getFieldBodyModel() -> returns($model) ); foreach ($params as $key => $value) { $this->_checking(Expectations::create() -> ignoring($header)->getParameter($key) -> returns($value) ); } if ($stub) { $this->_checking(Expectations::create() -> ignoring($header) ); } return $header; } protected function _createOutputStream($data = null, $stub = true) { $os = $this->_mock('Swift_OutputByteStream'); if (isset($data)) { $pos = $this->_mockery()->states('position')->startsAs('at beginning'); $this->_checking(Expectations::create() -> ignoring($os)->read(optional()) -> returns($data) -> when($pos->isNot('at end')) -> then($pos->is('at end')) -> ignoring($os)->read(optional()) -> returns(false) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($os) ); } } return $os; } protected function _createInputStream($stub = true) { $is = $this->_mock('Swift_InputByteStream'); if ($stub) { $this->_checking(Expectations::create() -> ignoring($is) ); } return $is; } // -- Mock helpers public function returnStringFromEncoder(Yay_Invocation $invocation) { $args = $invocation->getArguments(); return array_shift($args); } } Swift-4.2.1/tests/unit/Swift/Mime/AttachmentTest.php100644 0 0 25366 12000050367 17533 0ustar 0 0 _createAttachment($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual( Swift_Mime_MimeEntity::LEVEL_MIXED, $attachment->getNestingLevel() ); } public function testDispositionIsReturnedFromHeader() { /* -- RFC 2183, 2.1, 2.2. */ $disposition = $this->_createHeader('Content-Disposition', 'attachment'); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('attachment', $attachment->getDisposition()); } public function testDispositionIsSetInHeader() { $disposition = $this->_createHeader('Content-Disposition', 'attachment', array(), false ); $this->_checking(Expectations::create() -> one($disposition)->setFieldBodyModel('inline') -> ignoring($disposition) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $attachment->setDisposition('inline'); } public function testDispositionIsAddedIfNonePresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addParameterizedHeader('Content-Disposition', 'inline') -> ignoring($headers) ); $attachment = $this->_createAttachment($headers, $this->_createEncoder(), $this->_createCache() ); $attachment->setDisposition('inline'); } public function testDispositionIsAutoDefaultedToAttachment() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addParameterizedHeader('Content-Disposition', 'attachment') -> ignoring($headers) ); $attachment = $this->_createAttachment($headers, $this->_createEncoder(), $this->_createCache() ); } public function testDefaultContentTypeInitializedToOctetStream() { $cType = $this->_createHeader('Content-Type', '', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setFieldBodyModel('application/octet-stream') -> ignoring($cType) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); } public function testFilenameIsReturnedFromHeader() { /* -- RFC 2183, 2.3. */ $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('filename'=>'foo.txt') ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('foo.txt', $attachment->getFilename()); } public function testFilenameIsSetInHeader() { $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('filename'=>'foo.txt'), false ); $this->_checking(Expectations::create() -> one($disposition)->setParameter('filename', 'bar.txt') -> ignoring($disposition) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $attachment->setFilename('bar.txt'); } public function testSettingFilenameSetsNameInContentType() { /* This is a legacy requirement which isn't covered by up-to-date RFCs. */ $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false ); $this->_checking(Expectations::create() -> one($cType)->setParameter('name', 'bar.txt') -> ignoring($cType) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $attachment->setFilename('bar.txt'); } public function testSizeIsReturnedFromHeader() { /* -- RFC 2183, 2.7. */ $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('size'=>1234) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(1234, $attachment->getSize()); } public function testSizeIsSetInHeader() { $disposition = $this->_createHeader('Content-Disposition', 'attachment', array(), false ); $this->_checking(Expectations::create() -> one($disposition)->setParameter('size', 12345) -> ignoring($disposition) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $attachment->setSize(12345); } public function testFilnameCanBeReadFromFileStream() { $file = $this->_createFileStream('/bar/file.ext', ''); $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('filename'=>'foo.txt'), false ); $this->_checking(Expectations::create() -> one($disposition)->setParameter('filename', 'file.ext') -> ignoring($disposition) ); $attachment = $this->_createAttachment($this->_createHeaderSet(array( 'Content-Disposition' => $disposition)), $this->_createEncoder(), $this->_createCache() ); $attachment->setFile($file); } public function testContentTypeCanBeSetViaSetFile() { $file = $this->_createFileStream('/bar/file.ext', ''); $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('filename'=>'foo.txt'), false ); $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false); $headers = $this->_createHeaderSet(array( 'Content-Disposition' => $disposition, 'Content-Type' => $ctype )); $this->_checking(Expectations::create() -> one($disposition)->setParameter('filename', 'file.ext') -> one($ctype)->setFieldBodyModel('text/html') -> ignoring($disposition) -> ignoring($ctype) ); $attachment = $this->_createAttachment($headers, $this->_createEncoder(), $this->_createCache() ); $attachment->setFile($file, 'text/html'); } public function XtestContentTypeCanBeLookedUpFromCommonListIfNotProvided() { $file = $this->_createFileStream('/bar/file.zip', ''); $disposition = $this->_createHeader('Content-Disposition', 'attachment', array('filename'=>'foo.zip'), false ); $ctype = $this->_createHeader('Content-Type', 'text/plain', array(), false); $headers = $this->_createHeaderSet(array( 'Content-Disposition' => $disposition, 'Content-Type' => $ctype )); $this->_checking(Expectations::create() -> one($disposition)->setParameter('filename', 'file.zip') -> one($ctype)->setFieldBodyModel('application/zip') -> ignoring($disposition) -> ignoring($ctype) ); $attachment = $this->_createAttachment($headers, $this->_createEncoder(), $this->_createCache(), array('zip'=>'application/zip', 'txt'=>'text/plain') ); $attachment->setFile($file); } public function testDataCanBeReadFromFile() { $file = $this->_createFileStream('/foo/file.ext', ''); $attachment = $this->_createAttachment($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $attachment->setFile($file); $this->assertEqual('', $attachment->getBody()); } public function testFluidInterface() { $attachment = $this->_createAttachment($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertSame($attachment, $attachment ->setContentType('application/pdf') ->setEncoder($this->_createEncoder()) ->setId('foo@bar') ->setDescription('my pdf') ->setMaxLineLength(998) ->setBody('xx') ->setBoundary('xyz') ->setChildren(array()) ->setDisposition('inline') ->setFilename('afile.txt') ->setSize(123) ->setFile($this->_createFileStream('foo.txt', '')) ); } // -- Private helpers protected function _createEntity($headers, $encoder, $cache) { return $this->_createAttachment($headers, $encoder, $cache); } protected function _createAttachment($headers, $encoder, $cache, $mimeTypes = array()) { return new Swift_Mime_Attachment($headers, $encoder, $cache, new Swift_Mime_Grammar(), $mimeTypes); } protected function _createFileStream($path, $data, $stub = true) { $file = $this->_mock('Swift_FileStream'); $pos = $this->_mockery()->states('position')->startsAs('at start'); $this->_checking(Expectations::create() -> ignoring($file)->getPath() -> returns($path) -> ignoring($file)->read(optional()) -> returns($data) -> when($pos->isNot('at end')) -> then($pos->is('at end')) -> ignoring($file)->read(optional()) -> returns(false) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($file) ); } return $file; } } Swift-4.2.1/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php100644 0 0 26567 12000050367 24240 0ustar 0 0 getArguments(); $this->content .= current($args); } public function describeTo(Yay_Description $description) { $description->appendText(' gathers input;'); } } class Swift_Mime_ContentEncoder_Base64ContentEncoderTest extends Swift_Tests_SwiftUnitTestCase { private $_encoder; public function setUp() { $this->_encoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder(); } public function testNameIsBase64() { $this->assertEqual('base64', $this->_encoder->getName()); } /* There's really no point in testing the entire base64 encoding to the level QP encoding has been tested. base64_encode() has been in PHP for years. */ public function testInputOutputRatioIs3to4Bytes() { /* RFC 2045, 6.8 The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. */ $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('123') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is); $this->assertEqual('MTIz', $collection->content); } public function testPadLength() { /* RFC 2045, 6.8 Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a body. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the "=" character. Since all base64 input is an integral number of octets, only the following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ for ($i = 0; $i < 30; ++$i) { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns(pack('C', rand(0, 255))) -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is); $this->assertPattern('~^[a-zA-Z0-9/\+]{2}==$~', $collection->content, '%s: A single byte should have 2 bytes of padding' ); } for ($i = 0; $i < 30; ++$i) { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns(pack('C*', rand(0, 255), rand(0, 255))) -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is); $this->assertPattern('~^[a-zA-Z0-9/\+]{3}=$~', $collection->content, '%s: Two bytes should have 1 byte of padding' ); } for ($i = 0; $i < 30; ++$i) { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns(pack('C*', rand(0, 255), rand(0, 255), rand(0, 255))) -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is); $this->assertPattern('~^[a-zA-Z0-9/\+]{4}$~', $collection->content, '%s: Three bytes should have no padding' ); } } public function testMaximumLineLengthIs76Characters() { /* The encoded output stream must be represented in lines of no more than 76 characters each. All line breaks or other characters not found in Table 1 must be ignored by decoding software. */ $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('abcdefghijkl') //12 -> one($os)->read(optional()) -> returns('mnopqrstuvwx') //24 -> one($os)->read(optional()) -> returns('yzabc1234567') //36 -> one($os)->read(optional()) -> returns('890ABCDEFGHI') //48 -> one($os)->read(optional()) -> returns('JKLMNOPQRSTU') //60 -> one($os)->read(optional()) -> returns('VWXYZ1234567') //72 -> one($os)->read(optional()) -> returns('abcdefghijkl') //84 -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is); $this->assertEqual( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFS\r\n" . "U1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts", $collection->content ); } public function testMaximumLineLengthCanBeDifferent() { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('abcdefghijkl') //12 -> one($os)->read(optional()) -> returns('mnopqrstuvwx') //24 -> one($os)->read(optional()) -> returns('yzabc1234567') //36 -> one($os)->read(optional()) -> returns('890ABCDEFGHI') //48 -> one($os)->read(optional()) -> returns('JKLMNOPQRSTU') //60 -> one($os)->read(optional()) -> returns('VWXYZ1234567') //72 -> one($os)->read(optional()) -> returns('abcdefghijkl') //84 -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is, 0, 50); $this->assertEqual( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3OD\r\n" . "kwQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVoxMjM0NTY3YWJj\r\n" . "ZGVmZ2hpamts", $collection->content ); } public function testMaximumLineLengthIsNeverMoreThan76Chars() { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('abcdefghijkl') //12 -> one($os)->read(optional()) -> returns('mnopqrstuvwx') //24 -> one($os)->read(optional()) -> returns('yzabc1234567') //36 -> one($os)->read(optional()) -> returns('890ABCDEFGHI') //48 -> one($os)->read(optional()) -> returns('JKLMNOPQRSTU') //60 -> one($os)->read(optional()) -> returns('VWXYZ1234567') //72 -> one($os)->read(optional()) -> returns('abcdefghijkl') //84 -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is, 0, 100); $this->assertEqual( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFS\r\n" . "U1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts", $collection->content ); } public function testFirstLineLengthCanBeDifferent() { $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('abcdefghijkl') //12 -> one($os)->read(optional()) -> returns('mnopqrstuvwx') //24 -> one($os)->read(optional()) -> returns('yzabc1234567') //36 -> one($os)->read(optional()) -> returns('890ABCDEFGHI') //48 -> one($os)->read(optional()) -> returns('JKLMNOPQRSTU') //60 -> one($os)->read(optional()) -> returns('VWXYZ1234567') //72 -> one($os)->read(optional()) -> returns('abcdefghijkl') //84 -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $this->_encoder->encodeByteStream($os, $is, 19); $this->assertEqual( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmMxMjM0NTY3ODkwQUJDR\r\n" . "EVGR0hJSktMTU5PUFFSU1RVVldYWVoxMjM0NTY3YWJjZGVmZ2hpamts", $collection->content ); } // -- Private Methods private function _createOutputByteStream($stub = false) { return $stub ? $this->_stub('Swift_OutputByteStream') : $this->_mock('Swift_OutputByteStream') ; } private function _createInputByteStream($stub = false) { return $stub ? $this->_stub('Swift_InputByteStream') : $this->_mock('Swift_InputByteStream') ; } } Swift-4.2.1/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php100644 0 0 22004 12000050367 24235 0ustar 0 0 getArguments(); $this->content .= current($args); } public function describeTo(Yay_Description $description) { $description->appendText(' gathers input;'); } } class Swift_Mime_ContentEncoder_PlainContentEncoderTest extends Swift_Tests_SwiftUnitTestCase { public function testNameCanBeSpecifiedInConstructor() { $encoder = $this->_getEncoder('7bit'); $this->assertEqual('7bit', $encoder->getName()); $encoder = $this->_getEncoder('8bit'); $this->assertEqual('8bit', $encoder->getName()); } public function testNoOctetsAreModifiedInString() { $encoder = $this->_getEncoder('7bit'); foreach (range(0x00, 0xFF) as $octet) { $byte = pack('C', $octet); $this->assertIdenticalBinary($byte, $encoder->encodeString($byte)); } } public function testNoOctetsAreModifiedInByteStream() { $encoder = $this->_getEncoder('7bit'); foreach (range(0x00, 0xFF) as $octet) { $byte = pack('C', $octet); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns($byte) -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertIdenticalBinary($byte, $collection->content); } } public function testLineLengthCanBeSpecified() { $encoder = $this->_getEncoder('7bit'); $chars = array(); for ($i = 0; $i < 50; $i++) { $chars[] = 'a'; } $input = implode(' ', $chars); //99 chars long $this->assertEqual( 'a a a a a a a a a a a a a a a a a a a a a a a a a ' . "\r\n" . //50 * 'a a a a a a a a a a a a a a a a a a a a a a a a a', //99 $encoder->encodeString($input, 0, 50), '%s: Lines should be wrapped at 50 chars' ); } public function testLineLengthCanBeSpecifiedInByteStream() { $encoder = $this->_getEncoder('7bit'); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) ); for ($i = 0; $i < 50; $i++) { $this->_checking(Expectations::create() -> one($os)->read(optional()) -> returns('a ') ); } $this->_checking(Expectations::create() -> allowing($os)->read(optional()) -> returns(false) ); $encoder->encodeByteStream($os, $is, 0, 50); $this->assertEqual( str_repeat('a ', 25) . "\r\n" . str_repeat('a ', 25), $collection->content ); } public function testencodeStringGeneratesCorrectCrlf() { $encoder = $this->_getEncoder('7bit', true); $this->assertEqual("a\r\nb", $encoder->encodeString("a\rb"), '%s: Line endings should be standardized' ); $this->assertEqual("a\r\nb", $encoder->encodeString("a\nb"), '%s: Line endings should be standardized' ); $this->assertEqual("a\r\n\r\nb", $encoder->encodeString("a\n\rb"), '%s: Line endings should be standardized' ); $this->assertEqual("a\r\n\r\nb", $encoder->encodeString("a\r\rb"), '%s: Line endings should be standardized' ); $this->assertEqual("a\r\n\r\nb", $encoder->encodeString("a\n\nb"), '%s: Line endings should be standardized' ); } public function testCanonicEncodeByteStreamGeneratesCorrectCrlf_1() { $encoder = $this->_getEncoder('7bit', true); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('a') -> one($os)->read(optional()) -> returns("\r") -> one($os)->read(optional()) -> returns('b') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\nb", $collection->content); } public function testCanonicEncodeByteStreamGeneratesCorrectCrlf_2() { $encoder = $this->_getEncoder('7bit', true); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('a') -> one($os)->read(optional()) -> returns("\n") -> one($os)->read(optional()) -> returns('b') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\nb", $collection->content); } public function testCanonicEncodeByteStreamGeneratesCorrectCrlf_3() { $encoder = $this->_getEncoder('7bit', true); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('a') -> one($os)->read(optional()) -> returns("\n\r") -> one($os)->read(optional()) -> returns('b') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\n\r\nb", $collection->content); } public function testCanonicEncodeByteStreamGeneratesCorrectCrlf_4() { $encoder = $this->_getEncoder('7bit', true); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('a') -> one($os)->read(optional()) -> returns("\n\n") -> one($os)->read(optional()) -> returns('b') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\n\r\nb", $collection->content); } public function testCanonicEncodeByteStreamGeneratesCorrectCrlf_5() { $encoder = $this->_getEncoder('7bit', true); $os = $this->_createOutputByteStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> one($os)->read(optional()) -> returns('a') -> one($os)->read(optional()) -> returns("\r\r") -> one($os)->read(optional()) -> returns('b') -> allowing($os)->read(optional()) -> returns(false) -> ignoring($os) ); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\n\r\nb", $collection->content); } // -- Private helpers private function _getEncoder($name, $canonical = false) { return new Swift_Mime_ContentEncoder_PlainContentEncoder($name, $canonical); } private function _createOutputByteStream($stub = false) { return $stub ? $this->_stub('Swift_OutputByteStream') : $this->_mock('Swift_OutputByteStream') ; } private function _createInputByteStream($stub = false) { return $stub ? $this->_stub('Swift_InputByteStream') : $this->_mock('Swift_InputByteStream') ; } } Swift-4.2.1/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php100644 0 0 45614 12000050367 23566 0ustar 0 0 getArguments(); $this->content .= current($args); } public function describeTo(Yay_Description $description) { $description->appendText(' gathers input;'); } } class Swift_Mime_ContentEncoder_QpContentEncoderTest extends Swift_Tests_SwiftUnitTestCase { public function testNameIsQuotedPrintable() { $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder( $this->_createCharacterStream(true) ); $this->assertEqual('quoted-printable', $encoder->getName()); } /* -- RFC 2045, 6.7 -- (1) (General 8bit representation) Any octet, except a CR or LF that is part of a CRLF line break of the canonical (standard) form of the data being encoded, may be represented by an "=" followed by a two digit hexadecimal representation of the octet's value. The digits of the hexadecimal alphabet, for this purpose, are "0123456789ABCDEF". Uppercase letters must be used; lowercase letters are not allowed. Thus, for example, the decimal value 12 (US-ASCII form feed) can be represented by "=0C", and the decimal value 61 (US- ASCII EQUAL SIGN) can be represented by "=3D". This rule must be followed except when the following rules allow an alternative encoding. */ public function testPermittedCharactersAreNotEncoded() { /* -- RFC 2045, 6.7 -- (2) (Literal representation) Octets with decimal values of 33 through 60 inclusive, and 62 through 126, inclusive, MAY be represented as the US-ASCII characters which correspond to those octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN through TILDE, respectively). */ foreach (array_merge(range(33, 60), range(62, 126)) as $ordinal) { $char = chr($ordinal); $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array($ordinal)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertIdenticalBinary($char, $collection->content); } } public function testLinearWhiteSpaceAtLineEndingIsEncoded() { /* -- RFC 2045, 6.7 -- (3) (White Space) Octets with values of 9 and 32 MAY be represented as US-ASCII TAB (HT) and SPACE characters, respectively, but MUST NOT be so represented at the end of an encoded line. Any TAB (HT) or SPACE characters on an encoded line MUST thus be followed on that line by a printable character. In particular, an "=" at the end of an encoded line, indicating a soft line break (see rule #5) may follow one or more TAB (HT) or SPACE characters. It follows that an octet with decimal value 9 or 32 appearing at the end of an encoded line must be represented according to Rule #1. This rule is necessary because some MTAs (Message Transport Agents, programs which transport messages from one user to another, or perform a portion of such transfers) are known to pad lines of text with SPACEs, and others are known to remove "white space" characters from the end of a line. Therefore, when decoding a Quoted-Printable body, any trailing white space on a line must be deleted, as it will necessarily have been added by intermediate transport agents. */ $HT = chr(0x09); //9 $SPACE = chr(0x20); //32 //HT $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) -> one($charStream)->readBytes(any()) -> returns(array(0x09)) -> one($charStream)->readBytes(any()) -> returns(array(0x09)) -> one($charStream)->readBytes(any()) -> returns(array(0x0D)) -> one($charStream)->readBytes(any()) -> returns(array(0x0A)) -> one($charStream)->readBytes(any()) -> returns(array(ord('b'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\t=09\r\nb", $collection->content); //SPACE $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) -> one($charStream)->readBytes(any()) -> returns(array(0x20)) -> one($charStream)->readBytes(any()) -> returns(array(0x20)) -> one($charStream)->readBytes(any()) -> returns(array(0x0D)) -> one($charStream)->readBytes(any()) -> returns(array(0x0A)) -> one($charStream)->readBytes(any()) -> returns(array(ord('b'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual("a =20\r\nb", $collection->content); } public function testCRLFIsLeftAlone() { /* (4) (Line Breaks) A line break in a text body, represented as a CRLF sequence in the text canonical form, must be represented by a (RFC 822) line break, which is also a CRLF sequence, in the Quoted-Printable encoding. Since the canonical representation of media types other than text do not generally include the representation of line breaks as CRLF sequences, no hard line breaks (i.e. line breaks that are intended to be meaningful and to be displayed to the user) can occur in the quoted-printable encoding of such types. Sequences like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely appear in non-text data represented in quoted- printable, of course. Note that many implementations may elect to encode the local representation of various content types directly rather than converting to canonical form first, encoding, and then converting back to local representation. In particular, this may apply to plain text material on systems that use newline conventions other than a CRLF terminator sequence. Such an implementation optimization is permissible, but only when the combined canonicalization-encoding step is equivalent to performing the three steps separately. */ $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) -> one($charStream)->readBytes(any()) -> returns(array(0x0D)) -> one($charStream)->readBytes(any()) -> returns(array(0x0A)) -> one($charStream)->readBytes(any()) -> returns(array(ord('b'))) -> one($charStream)->readBytes(any()) -> returns(array(0x0D)) -> one($charStream)->readBytes(any()) -> returns(array(0x0A)) -> one($charStream)->readBytes(any()) -> returns(array(ord('c'))) -> one($charStream)->readBytes(any()) -> returns(array(0x0D)) -> one($charStream)->readBytes(any()) -> returns(array(0x0A)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual("a\r\nb\r\nc\r\n", $collection->content); } public function testLinesLongerThan76CharactersAreSoftBroken() { /* (5) (Soft Line Breaks) The Quoted-Printable encoding REQUIRES that encoded lines be no more than 76 characters long. If longer lines are to be encoded with the Quoted-Printable encoding, "soft" line breaks must be used. An equal sign as the last character on a encoded line indicates such a non-significant ("soft") line break in the encoded text. */ $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); for ($seq = 0; $seq <= 140; ++$seq) { $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) ); } $this->_checking(Expectations::create() -> allowing($charStream)->readBytes(any()) -> returns(false) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual(str_repeat('a', 75) . "=\r\n" . str_repeat('a', 66), $collection->content); } public function testMaxLineLengthCanBeSpecified() { $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); for ($seq = 0; $seq <= 100; ++$seq) { $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) ); } $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(false) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is, 0, 54); $this->assertEqual(str_repeat('a', 53) . "=\r\n" . str_repeat('a', 48), $collection->content); } public function testBytesBelowPermittedRangeAreEncoded() { /* According to Rule (1 & 2) */ foreach (range(0, 32) as $ordinal) { $char = chr($ordinal); $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array($ordinal)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual(sprintf('=%02X', $ordinal), $collection->content); } } public function testDecimalByte61IsEncoded() { /* According to Rule (1 & 2) */ $char = chr(61); $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array(61)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual(sprintf('=%02X', 61), $collection->content); } public function testBytesAbovePermittedRangeAreEncoded() { /* According to Rule (1 & 2) */ foreach (range(127, 255) as $ordinal) { $char = chr($ordinal); $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> one($charStream)->readBytes(any()) -> returns(array($ordinal)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is); $this->assertEqual(sprintf('=%02X', $ordinal), $collection->content); } } public function testFirstLineLengthCanBeDifferent() { $os = $this->_createOutputByteStream(true); $charStream = $this->_createCharacterStream(); $is = $this->_createInputByteStream(); $collection = new Swift_StreamCollector(); $this->_checking(Expectations::create() -> one($charStream)->flushContents() -> one($charStream)->importByteStream($os) -> allowing($is)->write(any(), optional()) -> will($collection) -> ignoring($is) -> ignoring($os) ); for ($seq = 0; $seq <= 140; ++$seq) { $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) ); } $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(false) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream); $encoder->encodeByteStream($os, $is, 22); $this->assertEqual( str_repeat('a', 53) . "=\r\n" . str_repeat('a', 75) . "=\r\n" . str_repeat('a', 13), $collection->content ); } public function testObserverInterfaceCanChangeCharset() { $stream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($stream)->setCharacterSet('windows-1252') -> ignoring($stream) ); $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($stream); $encoder->charsetChanged('windows-1252'); } // -- Creation Methods private function _createCharacterStream($stub = false) { return $stub ? $this->_stub('Swift_CharacterStream') : $this->_mock('Swift_CharacterStream') ; } private function _createEncoder($charStream) { return new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream); } private function _createOutputByteStream($stub = false) { return $stub ? $this->_stub('Swift_OutputByteStream') : $this->_mock('Swift_OutputByteStream') ; } private function _createInputByteStream($stub = false) { return $stub ? $this->_stub('Swift_InputByteStream') : $this->_mock('Swift_InputByteStream') ; } } Swift-4.2.1/tests/unit/Swift/Mime/EmbeddedFileTest.php100644 0 0 3640 12000050367 17703 0ustar 0 0 _createEmbeddedFile($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual( Swift_Mime_MimeEntity::LEVEL_RELATED, $file->getNestingLevel() ); } public function testIdIsAutoGenerated() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addIdHeader('Content-ID', pattern('/^.*?@.*?$/D')) -> ignoring($headers) ); $file = $this->_createEmbeddedFile($headers, $this->_createEncoder(), $this->_createCache() ); } public function testDefaultDispositionIsAttachment() { //Overridden } public function testDefaultDispositionIsInline() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addParameterizedHeader('Content-Disposition', 'inline') -> ignoring($headers) ); $file = $this->_createEmbeddedFile($headers, $this->_createEncoder(), $this->_createCache() ); } // -- Private helpers protected function _createAttachment($headers, $encoder, $cache, $mimeTypes = array()) { return $this->_createEmbeddedFile($headers, $encoder, $cache, $mimeTypes); } private function _createEmbeddedFile($headers, $encoder, $cache) { return new Swift_Mime_EmbeddedFile($headers, $encoder, $cache, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php100644 0 0 667 12000050367 23525 0ustar 0 0 assertEqual('B', $encoder->getName()); } } Swift-4.2.1/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php100644 0 0 21215 12000050367 23111 0ustar 0 0 _createEncoder( $this->_createCharacterStream(true) ); $this->assertEqual('Q', $encoder->getName()); } public function testSpaceAndTabNeverAppear() { /* -- RFC 2047, 4. Only a subset of the printable ASCII characters may be used in 'encoded-text'. Space and tab characters are not allowed, so that the beginning and end of an 'encoded-word' are obvious. */ $charStream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) -> one($charStream)->readBytes(any()) -> returns(array(0x20)) -> one($charStream)->readBytes(any()) -> returns(array(0x09)) -> one($charStream)->readBytes(any()) -> returns(array(0x20)) -> one($charStream)->readBytes(any()) -> returns(array(ord('b'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $this->assertNoPattern('~[ \t]~', $encoder->encodeString("a \t b"), '%s: encoded-words in headers cannot contain LWSP as per RFC 2047.' ); } public function testSpaceIsRepresentedByUnderscore() { /* -- RFC 2047, 4.2. (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be represented as "_" (underscore, ASCII 95.). (This character may not pass through some internetwork mail gateways, but its use will greatly enhance readability of "Q" encoded data with mail readers that do not support this encoding.) Note that the "_" always represents hexadecimal 20, even if the SPACE character occupies a different code position in the character set in use. */ $charStream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) -> one($charStream)->readBytes(any()) -> returns(array(0x20)) -> one($charStream)->readBytes(any()) -> returns(array(ord('b'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $this->assertEqual('a_b', $encoder->encodeString('a b'), '%s: Spaces can be represented by more readable underscores as per RFC 2047.' ); } public function testEqualsAndQuestionAndUnderscoreAreEncoded() { /* -- RFC 2047, 4.2. (3) 8-bit values which correspond to printable ASCII characters other than "=", "?", and "_" (underscore), MAY be represented as those characters. (But see section 5 for restrictions.) In particular, SPACE and TAB MUST NOT be represented as themselves within encoded words. */ $charStream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('='))) -> one($charStream)->readBytes(any()) -> returns(array(ord('?'))) -> one($charStream)->readBytes(any()) -> returns(array(ord('_'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $this->assertEqual('=3D=3F=5F', $encoder->encodeString('=?_'), '%s: Chars =, ? and _ (underscore) may not appear as per RFC 2047.' ); } public function testParensAndQuotesAreEncoded() { /* -- RFC 2047, 5 (2). A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT contain the characters "(", ")" or " */ $charStream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('('))) -> one($charStream)->readBytes(any()) -> returns(array(ord('"'))) -> one($charStream)->readBytes(any()) -> returns(array(ord(')'))) -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $this->assertEqual('=28=22=29', $encoder->encodeString('(")'), '%s: Chars (, " (DQUOTE) and ) may not appear as per RFC 2047.' ); } public function testOnlyCharactersAllowedInPhrasesAreUsed() { /* -- RFC 2047, 5. (3) As a replacement for a 'word' entity within a 'phrase', for example, one that precedes an address in a From, To, or Cc header. The ABNF definition for 'phrase' from RFC 822 thus becomes: phrase = 1*( encoded-word / word ) In this case the set of characters that may be used in a "Q"-encoded 'encoded-word' is restricted to: . An 'encoded-word' that appears within a 'phrase' MUST be separated from any adjacent 'word', 'text' or 'special' by 'linear-white-space'. */ $allowedBytes = array_merge( range(ord('a'), ord('z')), range(ord('A'), ord('Z')), range(ord('0'), ord('9')), array(ord('!'), ord('*'), ord('+'), ord('-'), ord('/')) ); foreach (range(0x00, 0xFF) as $byte) { $char = pack('C', $byte); $charStream = $this->_createCharacterStream(); $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array($byte)) -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $encodedChar = $encoder->encodeString($char); if (in_array($byte, $allowedBytes)) { $this->assertEqual($char, $encodedChar, '%s: Character ' . $char . ' should not be encoded.' ); } elseif (0x20 == $byte) //Special case { $this->assertEqual('_', $encodedChar, '%s: Space character should be replaced.' ); } else { $this->assertEqual(sprintf('=%02X', $byte), $encodedChar, '%s: Byte ' . $byte . ' should be encoded.' ); } } } public function testEqualsNeverAppearsAtEndOfLine() { /* -- RFC 2047, 5 (3). The 'encoded-text' in an 'encoded-word' must be self-contained; 'encoded-text' MUST NOT be continued from one 'encoded-word' to another. This implies that the 'encoded-text' portion of a "B" 'encoded-word' will be a multiple of 4 characters long; for a "Q" 'encoded-word', any "=" character that appears in the 'encoded-text' portion will be followed by two hexadecimal characters. */ $input = str_repeat('a', 140); $charStream = $this->_createCharacterStream(); $output = ''; $seq = 0; for (; $seq < 140; ++$seq) { $this->_checking(Expectations::create() -> one($charStream)->readBytes(any()) -> returns(array(ord('a'))) ); if (75 == $seq) { $output .= "\r\n"; // =\r\n } $output .= 'a'; } $this->_checking(Expectations::create() -> allowing($charStream)->readBytes(any()) -> returns(false) -> ignoring($charStream) ); $encoder = $this->_createEncoder($charStream); $this->assertEqual($output, $encoder->encodeString($input)); } // -- Creation Methods private function _createEncoder($charStream) { return new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream); } private function _createCharacterStream($stub = false) { return $stub ? $this->_stub('Swift_CharacterStream') : $this->_mock('Swift_CharacterStream') ; } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/DateHeaderTest.php100644 0 0 4223 12000050367 20751 0ustar 0 0 _getHeader('Date'); $this->assertEqual(Swift_Mime_Header::TYPE_DATE, $header->getFieldType()); } public function testGetTimestamp() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setTimestamp($timestamp); $this->assertIdentical($timestamp, $header->getTimestamp()); } public function testTimestampCanBeSetBySetter() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setTimestamp($timestamp); $this->assertIdentical($timestamp, $header->getTimestamp()); } public function testIntegerTimestampIsConvertedToRfc2822Date() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setTimestamp($timestamp); $this->assertEqual(date('r', $timestamp), $header->getFieldBody()); } public function testSetBodyModel() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setFieldBodyModel($timestamp); $this->assertEqual(date('r', $timestamp), $header->getFieldBody()); } public function testGetBodyModel() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setTimestamp($timestamp); $this->assertEqual($timestamp, $header->getFieldBodyModel()); } public function testToString() { $timestamp = time(); $header = $this->_getHeader('Date'); $header->setTimestamp($timestamp); $this->assertEqual('Date: ' . date('r', $timestamp) . "\r\n", $header->toString() ); } // -- Private methods private function _getHeader($name) { return new Swift_Mime_Headers_DateHeader($name, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php100644 0 0 13735 12000050367 23055 0ustar 0 0 _getHeader('Message-ID'); $this->assertEqual(Swift_Mime_Header::TYPE_ID, $header->getFieldType()); } public function testValueMatchesMsgIdSpec() { /* -- RFC 2822, 3.6.4. message-id = "Message-ID:" msg-id CRLF in-reply-to = "In-Reply-To:" 1*msg-id CRLF references = "References:" 1*msg-id CRLF msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] id-left = dot-atom-text / no-fold-quote / obs-id-left id-right = dot-atom-text / no-fold-literal / obs-id-right no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE no-fold-literal = "[" *(dtext / quoted-pair) "]" */ $header = $this->_getHeader('Message-ID'); $header->setId('id-left@id-right'); $this->assertEqual('', $header->getFieldBody()); } public function testIdCanBeRetrievedVerbatim() { $header = $this->_getHeader('Message-ID'); $header->setId('id-left@id-right'); $this->assertEqual('id-left@id-right', $header->getId()); } public function testMultipleIdsCanBeSet() { $header = $this->_getHeader('References'); $header->setIds(array('a@b', 'x@y')); $this->assertEqual(array('a@b', 'x@y'), $header->getIds()); } public function testSettingMultipleIdsProducesAListValue() { /* -- RFC 2822, 3.6.4. The "References:" and "In-Reply-To:" field each contain one or more unique message identifiers, optionally separated by CFWS. .. SNIP .. in-reply-to = "In-Reply-To:" 1*msg-id CRLF references = "References:" 1*msg-id CRLF */ $header = $this->_getHeader('References'); $header->setIds(array('a@b', 'x@y')); $this->assertEqual(' ', $header->getFieldBody()); } public function testIdLeftCanBeQuoted() { /* -- RFC 2822, 3.6.4. id-left = dot-atom-text / no-fold-quote / obs-id-left */ $header = $this->_getHeader('References'); $header->setId('"ab"@c'); $this->assertEqual('"ab"@c', $header->getId()); $this->assertEqual('<"ab"@c>', $header->getFieldBody()); } public function testIdLeftCanContainAnglesAsQuotedPairs() { /* -- RFC 2822, 3.6.4. no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE */ $header = $this->_getHeader('References'); $header->setId('"a\\<\\>b"@c'); $this->assertEqual('"a\\<\\>b"@c', $header->getId()); $this->assertEqual('<"a\\<\\>b"@c>', $header->getFieldBody()); } public function testIdLeftCanBeDotAtom() { $header = $this->_getHeader('References'); $header->setId('a.b+&%$.c@d'); $this->assertEqual('a.b+&%$.c@d', $header->getId()); $this->assertEqual('', $header->getFieldBody()); } public function testInvalidIdLeftThrowsException() { try { $header = $this->_getHeader('References'); $header->setId('a b c@d'); $this->fail( 'Exception should be thrown since "a b c" is not valid id-left.' ); } catch (Exception $e) { $this->pass(); } } public function testIdRightCanBeDotAtom() { /* -- RFC 2822, 3.6.4. id-right = dot-atom-text / no-fold-literal / obs-id-right */ $header = $this->_getHeader('References'); $header->setId('a@b.c+&%$.d'); $this->assertEqual('a@b.c+&%$.d', $header->getId()); $this->assertEqual('', $header->getFieldBody()); } public function testIdRightCanBeLiteral() { /* -- RFC 2822, 3.6.4. no-fold-literal = "[" *(dtext / quoted-pair) "]" */ $header = $this->_getHeader('References'); $header->setId('a@[1.2.3.4]'); $this->assertEqual('a@[1.2.3.4]', $header->getId()); $this->assertEqual('', $header->getFieldBody()); } public function testInvalidIdRightThrowsException() { try { $header = $this->_getHeader('References'); $header->setId('a@b c d'); $this->fail( 'Exception should be thrown since "b c d" is not valid id-right.' ); } catch (Exception $e) { $this->pass(); } } public function testMissingAtSignThrowsException() { /* -- RFC 2822, 3.6.4. msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] */ try { $header = $this->_getHeader('References'); $header->setId('abc'); $this->fail( 'Exception should be thrown since "abc" is does not contain @.' ); } catch (Exception $e) { $this->pass(); } } public function testSetBodyModel() { $header = $this->_getHeader('Message-ID'); $header->setFieldBodyModel('a@b'); $this->assertEqual(array('a@b'), $header->getIds()); } public function testGetBodyModel() { $header = $this->_getHeader('Message-ID'); $header->setId('a@b'); $this->assertEqual(array('a@b'), $header->getFieldBodyModel()); } public function testStringValue() { $header = $this->_getHeader('References'); $header->setIds(array('a@b', 'x@y')); $this->assertEqual('References: ' . "\r\n", $header->toString()); } // -- Private methods private function _getHeader($name) { return new Swift_Mime_Headers_IdentificationHeader($name, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php100644 0 0 27310 12000050367 21511 0ustar 0 0 _getHeader('To', $this->_getEncoder('Q', true)); $this->assertEqual(Swift_Mime_Header::TYPE_MAILBOX, $header->getFieldType()); } public function testMailboxIsSetForAddress() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses('chris@swiftmailer.org'); $this->assertEqual(array('chris@swiftmailer.org'), $header->getNameAddressStrings() ); } public function testMailboxIsRenderedForNameAddress() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn')); $this->assertEqual( array('Chris Corbyn '), $header->getNameAddressStrings() ); } public function testAddressCanBeReturnedForAddress() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses('chris@swiftmailer.org'); $this->assertEqual(array('chris@swiftmailer.org'), $header->getAddresses()); } public function testAddressCanBeReturnedForNameAddress() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn')); $this->assertEqual(array('chris@swiftmailer.org'), $header->getAddresses()); } public function testQuotesInNameAreQuoted() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn, "DHE"' )); $this->assertEqual( array('"Chris Corbyn, \"DHE\"" '), $header->getNameAddressStrings() ); } public function testEscapeCharsInNameAreQuoted() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn, \\escaped\\' )); $this->assertEqual( array('"Chris Corbyn, \\\\escaped\\\\" '), $header->getNameAddressStrings() ); } public function testGetMailboxesReturnsNameValuePairs() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn, DHE' )); $this->assertEqual( array('chris@swiftmailer.org' => 'Chris Corbyn, DHE'), $header->getNameAddresses() ); } public function testMultipleAddressesCanBeSetAndFetched() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses(array( 'chris@swiftmailer.org', 'mark@swiftmailer.org' )); $this->assertEqual( array('chris@swiftmailer.org', 'mark@swiftmailer.org'), $header->getAddresses() ); } public function testMultipleAddressesAsMailboxes() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses(array( 'chris@swiftmailer.org', 'mark@swiftmailer.org' )); $this->assertEqual( array('chris@swiftmailer.org'=>null, 'mark@swiftmailer.org'=>null), $header->getNameAddresses() ); } public function testMultipleAddressesAsMailboxStrings() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses(array( 'chris@swiftmailer.org', 'mark@swiftmailer.org' )); $this->assertEqual( array('chris@swiftmailer.org', 'mark@swiftmailer.org'), $header->getNameAddressStrings() ); } public function testMultipleNamedMailboxesReturnsMultipleAddresses() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual( array('chris@swiftmailer.org', 'mark@swiftmailer.org'), $header->getAddresses() ); } public function testMultipleNamedMailboxesReturnsMultipleMailboxes() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' ), $header->getNameAddresses() ); } public function testMultipleMailboxesProducesMultipleMailboxStrings() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual(array( 'Chris Corbyn ', 'Mark Corbyn ' ), $header->getNameAddressStrings() ); } public function testSetAddressesOverwritesAnyMailboxes() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual( array('chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn'), $header->getNameAddresses() ); $this->assertEqual( array('chris@swiftmailer.org', 'mark@swiftmailer.org'), $header->getAddresses() ); $header->setAddresses(array('chris@swiftmailer.org', 'mark@swiftmailer.org')); $this->assertEqual( array('chris@swiftmailer.org' => null, 'mark@swiftmailer.org' => null), $header->getNameAddresses() ); $this->assertEqual( array('chris@swiftmailer.org', 'mark@swiftmailer.org'), $header->getAddresses() ); } public function testNameIsEncodedIfNonAscii() { $name = 'C' . pack('C', 0x8F) . 'rbyn'; $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($name, any(), any()) -> returns('C=8Frbyn') -> ignoring($encoder) ); $header = $this->_getHeader('From', $encoder); $header->setNameAddresses(array('chris@swiftmailer.org'=>'Chris ' . $name)); $addresses = $header->getNameAddressStrings(); $this->assertEqual( 'Chris =?' . $this->_charset . '?Q?C=8Frbyn?= ', array_shift($addresses) ); } public function testEncodingLineLengthCalculations() { /* -- RFC 2047, 2. An 'encoded-word' may not be more than 75 characters long, including 'charset', 'encoding', 'encoded-text', and delimiters. */ $name = 'C' . pack('C', 0x8F) . 'rbyn'; $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($name, 6, 63) -> returns('C=8Frbyn') -> ignoring($encoder) ); $header = $this->_getHeader('From', $encoder); $header->setNameAddresses(array('chris@swiftmailer.org'=>'Chris ' . $name)); $header->getNameAddressStrings(); } public function testGetValueReturnsMailboxStringValue() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn' )); $this->assertEqual( 'Chris Corbyn ', $header->getFieldBody() ); } public function testGetValueReturnsMailboxStringValueForMultipleMailboxes() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual( 'Chris Corbyn , Mark Corbyn ', $header->getFieldBody() ); } public function testRemoveAddressesWithSingleValue() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $header->removeAddresses('chris@swiftmailer.org'); $this->assertEqual(array('mark@swiftmailer.org'), $header->getAddresses() ); } public function testRemoveAddressesWithList() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $header->removeAddresses( array('chris@swiftmailer.org', 'mark@swiftmailer.org') ); $this->assertEqual(array(), $header->getAddresses()); } public function testSetBodyModel() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setFieldBodyModel('chris@swiftmailer.org'); $this->assertEqual(array('chris@swiftmailer.org'=>null), $header->getNameAddresses()); } public function testGetBodyModel() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setAddresses(array('chris@swiftmailer.org')); $this->assertEqual(array('chris@swiftmailer.org'=>null), $header->getFieldBodyModel()); } public function testToString() { $header = $this->_getHeader('From', $this->_getEncoder('Q', true)); $header->setNameAddresses(array( 'chris@swiftmailer.org' => 'Chris Corbyn', 'mark@swiftmailer.org' => 'Mark Corbyn' )); $this->assertEqual( 'From: Chris Corbyn , ' . 'Mark Corbyn ' . "\r\n", $header->toString() ); } // -- Private methods private function _getHeader($name, $encoder) { $header = new Swift_Mime_Headers_MailboxHeader($name, $encoder, new Swift_Mime_Grammar()); $header->setCharset($this->_charset); return $header; } private function _getEncoder($type, $stub = false) { $encoder = $this->_mock('Swift_Mime_HeaderEncoder'); $this->_checking(Expectations::create() -> ignoring($encoder)->getName() -> returns($type) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($encoder) ); } return $encoder; } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php100644 0 0 37105 12000050367 22715 0ustar 0 0 _getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $this->assertEqual(Swift_Mime_Header::TYPE_PARAMETERIZED, $header->getFieldType()); } public function testValueIsReturnedVerbatim() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setValue('text/plain'); $this->assertEqual('text/plain', $header->getValue()); } public function testParametersAreAppended() { /* -- RFC 2045, 5.1 parameter := attribute "=" value attribute := token ; Matching of attributes ; is ALWAYS case-insensitive. value := token / quoted-string token := 1* tspecials := "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" / <"> "/" / "[" / "]" / "?" / "=" ; Must be in quoted-string, ; to use within parameter values */ $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setValue('text/plain'); $header->setParameters(array('charset' => 'utf-8')); $this->assertEqual('text/plain; charset=utf-8', $header->getFieldBody()); } public function testSpaceInParamResultsInQuotedString() { $header = $this->_getHeader('Content-Disposition', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setValue('attachment'); $header->setParameters(array('filename' => 'my file.txt')); $this->assertEqual('attachment; filename="my file.txt"', $header->getFieldBody() ); } public function testLongParamsAreBrokenIntoMultipleAttributeStrings() { /* -- RFC 2231, 3. The asterisk character ("*") followed by a decimal count is employed to indicate that multiple parameters are being used to encapsulate a single parameter value. The count starts at 0 and increments by 1 for each subsequent section of the parameter value. Decimal values are used and neither leading zeroes nor gaps in the sequence are allowed. The original parameter value is recovered by concatenating the various sections of the parameter, in order. For example, the content-type field Content-Type: message/external-body; access-type=URL; URL*0="ftp://"; URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" is semantically identical to Content-Type: message/external-body; access-type=URL; URL="ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" Note that quotes around parameter values are part of the value syntax; they are NOT part of the value itself. Furthermore, it is explicitly permitted to have a mixture of quoted and unquoted continuation fields. */ $value = str_repeat('a', 180); $encoder = $this->_getParameterEncoder(); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), 63) -> returns(str_repeat('a', 63) . "\r\n" . str_repeat('a', 63) . "\r\n" . str_repeat('a', 54)) -> ignoring($encoder) ); $header = $this->_getHeader('Content-Disposition', $this->_getHeaderEncoder('Q', true), $encoder ); $header->setValue('attachment'); $header->setParameters(array('filename' => $value)); $header->setMaxLineLength(78); $this->assertEqual( 'attachment; ' . 'filename*0*=utf-8\'\'' . str_repeat('a', 63) . ";\r\n " . 'filename*1*=' . str_repeat('a', 63) . ";\r\n " . 'filename*2*=' . str_repeat('a', 54), $header->getFieldBody() ); } public function testEncodedParamDataIncludesCharsetAndLanguage() { /* -- RFC 2231, 4. Asterisks ("*") are reused to provide the indicator that language and character set information is present and encoding is being used. A single quote ("'") is used to delimit the character set and language information at the beginning of the parameter value. Percent signs ("%") are used as the encoding flag, which agrees with RFC 2047. Specifically, an asterisk at the end of a parameter name acts as an indicator that character set and language information may appear at the beginning of the parameter value. A single quote is used to separate the character set, language, and actual value information in the parameter value string, and an percent sign is used to flag octets encoded in hexadecimal. For example: Content-Type: application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A Note that it is perfectly permissible to leave either the character set or language field blank. Note also that the single quote delimiters MUST be present even when one of the field values is omitted. */ $value = str_repeat('a', 20) . pack('C', 0x8F) . str_repeat('a', 10); $encoder = $this->_getParameterEncoder(); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, 12, 62) -> returns(str_repeat('a', 20) . '%8F' . str_repeat('a', 10)) -> ignoring($encoder) ); $header = $this->_getHeader('Content-Disposition', $this->_getHeaderEncoder('Q', true), $encoder ); $header->setValue('attachment'); $header->setParameters(array('filename' => $value)); $header->setMaxLineLength(78); $header->setLanguage($this->_lang); $this->assertEqual( 'attachment; filename*=' . $this->_charset . "'" . $this->_lang . "'" . str_repeat('a', 20) . '%8F' . str_repeat('a', 10), $header->getFieldBody() ); } public function testMultipleEncodedParamLinesAreFormattedCorrectly() { /* -- RFC 2231, 4.1. Character set and language information may be combined with the parameter continuation mechanism. For example: Content-Type: application/x-stuff title*0*=us-ascii'en'This%20is%20even%20more%20 title*1*=%2A%2A%2Afun%2A%2A%2A%20 title*2="isn't it!" Note that: (1) Language and character set information only appear at the beginning of a given parameter value. (2) Continuations do not provide a facility for using more than one character set or language in the same parameter value. (3) A value presented using multiple continuations may contain a mixture of encoded and unencoded segments. (4) The first segment of a continuation MUST be encoded if language and character set information are given. (5) If the first segment of a continued parameter value is encoded the language and character set field delimiters MUST be present even when the fields are left blank. */ $value = str_repeat('a', 20) . pack('C', 0x8F) . str_repeat('a', 60); $encoder = $this->_getParameterEncoder(); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, 12, 62) -> returns(str_repeat('a', 20) . '%8F' . str_repeat('a', 28) . "\r\n" . str_repeat('a', 32)) -> ignoring($encoder) ); $header = $this->_getHeader('Content-Disposition', $this->_getHeaderEncoder('Q', true), $encoder ); $header->setValue('attachment'); $header->setParameters(array('filename' => $value)); $header->setMaxLineLength(78); $header->setLanguage($this->_lang); $this->assertEqual( 'attachment; filename*0*=' . $this->_charset . "'" . $this->_lang . "'" . str_repeat('a', 20) . '%8F' . str_repeat('a', 28) . ";\r\n " . 'filename*1*=' . str_repeat('a', 32), $header->getFieldBody() ); } public function testToString() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setValue('text/html'); $header->setParameters(array('charset' => 'utf-8')); $this->assertEqual('Content-Type: text/html; charset=utf-8' . "\r\n", $header->toString() ); } public function testValueCanBeEncodedIfNonAscii() { $value = 'fo' . pack('C', 0x8F) .'bar'; $encoder = $this->_getHeaderEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), any()) -> returns('fo=8Fbar') -> ignoring($encoder) ); $header = $this->_getHeader('X-Foo', $encoder, $this->_getParameterEncoder(true)); $header->setValue($value); $header->setParameters(array('lookslike' => 'foobar')); $this->assertEqual('X-Foo: =?utf-8?Q?fo=8Fbar?=; lookslike=foobar' . "\r\n", $header->toString() ); } public function testValueAndParamCanBeEncodedIfNonAscii() { $value = 'fo' . pack('C', 0x8F) .'bar'; $encoder = $this->_getHeaderEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), any()) -> returns('fo=8Fbar') -> ignoring($encoder) ); $paramEncoder = $this->_getParameterEncoder(); $this->_checking(Expectations::create() -> one($paramEncoder)->encodeString($value, any(), any()) -> returns('fo%8Fbar') -> ignoring($paramEncoder) ); $header = $this->_getHeader('X-Foo', $encoder, $paramEncoder); $header->setValue($value); $header->setParameters(array('says' => $value)); $this->assertEqual("X-Foo: =?utf-8?Q?fo=8Fbar?=; says*=utf-8''fo%8Fbar\r\n", $header->toString() ); } public function testParamsAreEncodedWithEncodedWordsIfNoParamEncoderSet() { $value = 'fo' . pack('C', 0x8F) .'bar'; $encoder = $this->_getHeaderEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), any()) -> returns('fo=8Fbar') -> ignoring($encoder) ); $header = $this->_getHeader('X-Foo', $encoder, null); $header->setValue('bar'); $header->setParameters(array('says' => $value)); $this->assertEqual("X-Foo: bar; says=\"=?utf-8?Q?fo=8Fbar?=\"\r\n", $header->toString() ); } public function testLanguageInformationAppearsInEncodedWords() { /* -- RFC 2231, 5. 5. Language specification in Encoded Words RFC 2047 provides support for non-US-ASCII character sets in RFC 822 message header comments, phrases, and any unstructured text field. This is done by defining an encoded word construct which can appear in any of these places. Given that these are fields intended for display, it is sometimes necessary to associate language information with encoded words as well as just the character set. This specification extends the definition of an encoded word to allow the inclusion of such information. This is simply done by suffixing the character set specification with an asterisk followed by the language tag. For example: From: =?US-ASCII*EN?Q?Keith_Moore?= */ $value = 'fo' . pack('C', 0x8F) .'bar'; $encoder = $this->_getHeaderEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), any()) -> returns('fo=8Fbar') -> ignoring($encoder) ); $paramEncoder = $this->_getParameterEncoder(); $this->_checking(Expectations::create() -> one($paramEncoder)->encodeString($value, any(), any()) -> returns('fo%8Fbar') -> ignoring($paramEncoder) ); $header = $this->_getHeader('X-Foo', $encoder, $paramEncoder); $header->setLanguage('en'); $header->setValue($value); $header->setParameters(array('says' => $value)); $this->assertEqual("X-Foo: =?utf-8*en?Q?fo=8Fbar?=; says*=utf-8'en'fo%8Fbar\r\n", $header->toString() ); } public function testSetBodyModel() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setFieldBodyModel('text/html'); $this->assertEqual('text/html', $header->getValue()); } public function testGetBodyModel() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setValue('text/plain'); $this->assertEqual('text/plain', $header->getFieldBodyModel()); } public function testSetParameter() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setParameters(array('charset'=>'utf-8', 'delsp' => 'yes')); $header->setParameter('delsp', 'no'); $this->assertEqual(array('charset'=>'utf-8', 'delsp'=>'no'), $header->getParameters() ); } public function testGetParameter() { $header = $this->_getHeader('Content-Type', $this->_getHeaderEncoder('Q', true), $this->_getParameterEncoder(true) ); $header->setParameters(array('charset'=>'utf-8', 'delsp' => 'yes')); $this->assertEqual('utf-8', $header->getParameter('charset')); } // -- Private helper private function _getHeader($name, $encoder, $paramEncoder) { $header = new Swift_Mime_Headers_ParameterizedHeader($name, $encoder, $paramEncoder, new Swift_Mime_Grammar() ); $header->setCharset($this->_charset); return $header; } private function _getHeaderEncoder($type, $stub = false) { $encoder = $this->_mock('Swift_Mime_HeaderEncoder'); $this->_checking(Expectations::create() -> ignoring($encoder)->getName() -> returns($type) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($encoder) ); } return $encoder; } private function _getParameterEncoder($stub = false) { if ($stub) { return $this->_stub('Swift_Encoder'); } else { return $this->_mock('Swift_Encoder'); } } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/PathHeaderTest.php100644 0 0 5131 12000050367 20767 0ustar 0 0 _getHeader('Return-Path'); $this->assertEqual(Swift_Mime_Header::TYPE_PATH, $header->getFieldType()); } public function testSingleAddressCanBeSetAndFetched() { $header = $this->_getHeader('Return-Path'); $header->setAddress('chris@swiftmailer.org'); $this->assertEqual('chris@swiftmailer.org', $header->getAddress()); } public function testAddressMustComplyWithRfc2822() { try { $header = $this->_getHeader('Return-Path'); $header->setAddress('chr is@swiftmailer.org'); $this->fail('Address must be valid according to RFC 2822 addr-spec grammar.'); } catch (Exception $e) { $this->pass(); } } public function testValueIsAngleAddrWithValidAddress() { /* -- RFC 2822, 3.6.7. return = "Return-Path:" path CRLF path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / obs-path */ $header = $this->_getHeader('Return-Path'); $header->setAddress('chris@swiftmailer.org'); $this->assertEqual('', $header->getFieldBody()); } public function testValueIsEmptyAngleBracketsIfEmptyAddressSet() { $header = $this->_getHeader('Return-Path'); $header->setAddress(''); $this->assertEqual('<>', $header->getFieldBody()); } public function testSetBodyModel() { $header = $this->_getHeader('Return-Path'); $header->setFieldBodyModel('foo@bar.tld'); $this->assertEqual('foo@bar.tld', $header->getAddress()); } public function testGetBodyModel() { $header = $this->_getHeader('Return-Path'); $header->setAddress('foo@bar.tld'); $this->assertEqual('foo@bar.tld', $header->getFieldBodyModel()); } public function testToString() { $header = $this->_getHeader('Return-Path'); $header->setAddress('chris@swiftmailer.org'); $this->assertEqual('Return-Path: ' . "\r\n", $header->toString() ); } // -- Private methods private function _getHeader($name) { return new Swift_Mime_Headers_PathHeader($name, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php100644 0 0 32441 12000050367 22626 0ustar 0 0 _getHeader('Subject', $this->_getEncoder('Q', true)); $this->assertEqual(Swift_Mime_Header::TYPE_TEXT, $header->getFieldType()); } public function testGetNameReturnsNameVerbatim() { $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true)); $this->assertEqual('Subject', $header->getFieldName()); } public function testGetValueReturnsValueVerbatim() { $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true)); $header->setValue('Test'); $this->assertEqual('Test', $header->getValue()); } public function testBasicStructureIsKeyValuePair() { /* -- RFC 2822, 2.2 Header fields are lines composed of a field name, followed by a colon (":"), followed by a field body, and terminated by CRLF. */ $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true)); $header->setValue('Test'); $this->assertEqual('Subject: Test' . "\r\n", $header->toString()); } public function testLongHeadersAreFoldedAtWordBoundary() { /* -- RFC 2822, 2.2.3 Each header field is logically a single line of characters comprising the field name, the colon, and the field body. For convenience however, and to deal with the 998/78 character limitations per line, the field body portion of a header field can be split into a multiple line representation; this is called "folding". The general rule is that wherever this standard allows for folding white space (not simply WSP characters), a CRLF may be inserted before any WSP. */ $value = 'The quick brown fox jumped over the fence, he was a very very ' . 'scary brown fox with a bushy tail'; $header = $this->_getHeader('X-Custom-Header', $this->_getEncoder('Q', true) ); $header->setValue($value); $header->setMaxLineLength(78); //A safe [RFC 2822, 2.2.3] default /* X-Custom-Header: The quick brown fox jumped over the fence, he was a very very scary brown fox with a bushy tail */ $this->assertEqual( 'X-Custom-Header: The quick brown fox jumped over the fence, he was a' . ' very very' . "\r\n" . //Folding ' scary brown fox with a bushy tail' . "\r\n", $header->toString(), '%s: The header should have been folded at 78th char' ); } public function testPrintableAsciiOnlyAppearsInHeaders() { /* -- RFC 2822, 2.2. A field name MUST be composed of printable US-ASCII characters (i.e., characters that have values between 33 and 126, inclusive), except colon. A field body may be composed of any US-ASCII characters, except for CR and LF. */ $nonAsciiChar = pack('C', 0x8F); $header = $this->_getHeader('X-Test', $this->_getEncoder('Q', true)); $header->setValue($nonAsciiChar); $this->assertPattern( '~^[^:\x00-\x20\x80-\xFF]+: [^\x80-\xFF\r\n]+\r\n$~s', $header->toString() ); } public function testEncodedWordsFollowGeneralStructure() { /* -- RFC 2047, 1. Generally, an "encoded-word" is a sequence of printable ASCII characters that begins with "=?", ends with "?=", and has two "?"s in between. */ $nonAsciiChar = pack('C', 0x8F); $header = $this->_getHeader('X-Test', $this->_getEncoder('Q', true)); $header->setValue($nonAsciiChar); $this->assertPattern( '~^X-Test: \=?.*?\?.*?\?.*?\?=\r\n$~s', $header->toString() ); } public function testEncodedWordIncludesCharsetAndEncodingMethodAndText() { /* -- RFC 2047, 2. An 'encoded-word' is defined by the following ABNF grammar. The notation of RFC 822 is used, with the exception that white space characters MUST NOT appear between components of an 'encoded-word'. encoded-word = "=?" charset "?" encoding "?" encoded-text "?=" */ $nonAsciiChar = pack('C', 0x8F); $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($nonAsciiChar, any(), any()) -> returns('=8F') -> ignoring($encoder) ); $header = $this->_getHeader('X-Test', $encoder); $header->setValue($nonAsciiChar); $this->assertEqual( 'X-Test: =?' . $this->_charset . '?Q?=8F?=' . "\r\n", $header->toString() ); } public function testEncodedWordsAreUsedToEncodedNonPrintableAscii() { //SPACE and TAB permitted $nonPrintableBytes = array_merge( range(0x00, 0x08), range(0x10, 0x19), array(0x7F) ); foreach ($nonPrintableBytes as $byte) { $char = pack('C', $byte); $encodedChar = sprintf('=%02X', $byte); $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($char, any(), any()) -> returns($encodedChar) -> ignoring($encoder) ); $header = $this->_getHeader('X-A', $encoder); $header->setValue($char); $this->assertEqual( 'X-A: =?' . $this->_charset . '?Q?' . $encodedChar . '?=' . "\r\n", $header->toString(), '%s: Non-printable ascii should be encoded' ); } } public function testEncodedWordsAreUsedToEncode8BitOctets() { $_8BitBytes = range(0x80, 0xFF); foreach ($_8BitBytes as $byte) { $char = pack('C', $byte); $encodedChar = sprintf('=%02X', $byte); $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($char, any(), any()) -> returns($encodedChar) -> ignoring($encoder) ); $header = $this->_getHeader('X-A', $encoder); $header->setValue($char); $this->assertEqual( 'X-A: =?' . $this->_charset . '?Q?' . $encodedChar . '?=' . "\r\n", $header->toString(), '%s: 8-bit octets should be encoded' ); } } public function testEncodedWordsAreNoMoreThan75CharsPerLine() { /* -- RFC 2047, 2. An 'encoded-word' may not be more than 75 characters long, including 'charset', 'encoding', 'encoded-text', and delimiters. ... SNIP ... While there is no limit to the length of a multiple-line header field, each line of a header field that contains one or more 'encoded-word's is limited to 76 characters. */ $nonAsciiChar = pack('C', 0x8F); $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($nonAsciiChar, 8, 63) -> returns('=8F') -> ignoring($encoder) ); //Note that multi-line headers begin with LWSP which makes 75 + 1 = 76 //Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63 //* X-Test: is 8 chars $header = $this->_getHeader('X-Test', $encoder); $header->setValue($nonAsciiChar); $this->assertEqual( 'X-Test: =?' . $this->_charset . '?Q?=8F?=' . "\r\n", $header->toString() ); } public function testFWSPIsUsedWhenEncoderReturnsMultipleLines() { /* --RFC 2047, 2. If it is desirable to encode more text than will fit in an 'encoded-word' of 75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may be used. */ //Note the Mock does NOT return 8F encoded, the 8F merely triggers // encoding for the sake of testing $nonAsciiChar = pack('C', 0x8F); $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($nonAsciiChar, 8, 63) -> returns('line_one_here' . "\r\n" . 'line_two_here') -> ignoring($encoder) ); //Note that multi-line headers begin with LWSP which makes 75 + 1 = 76 //Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63 //* X-Test: is 8 chars $header = $this->_getHeader('X-Test', $encoder); $header->setValue($nonAsciiChar); $this->assertEqual( 'X-Test: =?' . $this->_charset . '?Q?line_one_here?=' . "\r\n" . ' =?' . $this->_charset . '?Q?line_two_here?=' . "\r\n", $header->toString() ); } public function testAdjacentWordsAreEncodedTogether() { /* -- RFC 2047, 5 (1) Ordinary ASCII text and 'encoded-word's may appear together in the same header field. However, an 'encoded-word' that appears in a header field defined as '*text' MUST be separated from any adjacent 'encoded-word' or 'text' by 'linear-white-space'. -- RFC 2047, 2. IMPORTANT: 'encoded-word's are designed to be recognized as 'atom's by an RFC 822 parser. As a consequence, unencoded white space characters (such as SPACE and HTAB) are FORBIDDEN within an 'encoded-word'. */ //It would be valid to encode all words needed, however it's probably // easiest to encode the longest amount required at a time $word = 'w' . pack('C', 0x8F) . 'rd'; $text = 'start ' . $word . ' ' . $word . ' then end ' . $word; // 'start', ' word word', ' and end', ' word' $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($word . ' ' . $word, any(), any()) -> returns('w=8Frd_w=8Frd') -> one($encoder)->encodeString($word, any(), any()) -> returns('w=8Frd') -> ignoring($encoder) ); $header = $this->_getHeader('X-Test', $encoder); $header->setValue($text); $headerString = $header->toString(); $this->assertEqual('X-Test: start =?' . $this->_charset . '?Q?' . 'w=8Frd_w=8Frd?= then end =?' . $this->_charset . '?Q?'. 'w=8Frd?=' . "\r\n", $headerString, '%s: Adjacent encoded words should appear grouped with WSP encoded' ); } public function testLanguageInformationAppearsInEncodedWords() { /* -- RFC 2231, 5. 5. Language specification in Encoded Words RFC 2047 provides support for non-US-ASCII character sets in RFC 822 message header comments, phrases, and any unstructured text field. This is done by defining an encoded word construct which can appear in any of these places. Given that these are fields intended for display, it is sometimes necessary to associate language information with encoded words as well as just the character set. This specification extends the definition of an encoded word to allow the inclusion of such information. This is simply done by suffixing the character set specification with an asterisk followed by the language tag. For example: From: =?US-ASCII*EN?Q?Keith_Moore?= */ $value = 'fo' . pack('C', 0x8F) . 'bar'; $encoder = $this->_getEncoder('Q'); $this->_checking(Expectations::create() -> one($encoder)->encodeString($value, any(), any()) -> returns('fo=8Fbar') -> ignoring($encoder) ); $header = $this->_getHeader('Subject', $encoder); $header->setLanguage('en'); $header->setValue($value); $this->assertEqual("Subject: =?utf-8*en?Q?fo=8Fbar?=\r\n", $header->toString() ); } public function testSetBodyModel() { $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true)); $header->setFieldBodyModel('test'); $this->assertEqual('test', $header->getValue()); } public function testGetBodyModel() { $header = $this->_getHeader('Subject', $this->_getEncoder('Q', true)); $header->setValue('test'); $this->assertEqual('test', $header->getFieldBodyModel()); } // -- Private methods private function _getHeader($name, $encoder) { $header = new Swift_Mime_Headers_UnstructuredHeader($name, $encoder, new Swift_Mime_Grammar()); $header->setCharset($this->_charset); return $header; } private function _getEncoder($type, $stub = false) { $encoder = $this->_mock('Swift_Mime_HeaderEncoder'); $this->_checking(Expectations::create() -> ignoring($encoder)->getName() -> returns($type) ); if ($stub) { $this->_checking(Expectations::create() -> ignoring($encoder) ); } return $encoder; } } Swift-4.2.1/tests/unit/Swift/Mime/MimePartTest.php100644 0 0 20353 12000050367 17150 0ustar 0 0 _createMimePart($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual( Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, $part->getNestingLevel() ); } public function testCharsetIsReturnedFromHeader() { /* -- RFC 2046, 4.1.2. A critical parameter that may be specified in the Content-Type field for "text/plain" data is the character set. This is specified with a "charset" parameter, as in: Content-type: text/plain; charset=iso-8859-1 Unlike some other parameter values, the values of the charset parameter are NOT case sensitive. The default character set, which must be assumed in the absence of a charset parameter, is US-ASCII. */ $cType = $this->_createHeader('Content-Type', 'text/plain', array('charset' => 'iso-8859-1') ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('iso-8859-1', $part->getCharset()); } public function testCharsetIsSetInHeader() { $cType = $this->_createHeader('Content-Type', 'text/plain', array('charset' => 'iso-8859-1'), false ); $this->_checking(Expectations::create() -> one($cType)->setParameter('charset', 'utf-8') -> ignoring($cType) ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $part->setCharset('utf-8'); } public function testCharsetIsSetInHeaderIfPassedToSetBody() { $cType = $this->_createHeader('Content-Type', 'text/plain', array('charset' => 'iso-8859-1'), false ); $this->_checking(Expectations::create() -> one($cType)->setParameter('charset', 'utf-8') -> ignoring($cType) ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $part->setBody('', 'text/plian', 'utf-8'); } public function testSettingCharsetNotifiesEncoder() { $encoder = $this->_createEncoder('quoted-printable', false); $this->_checking(Expectations::create() -> one($encoder)->charsetChanged('utf-8') -> ignoring($encoder) ); $part = $this->_createMimePart($this->_createHeaderSet(), $encoder, $this->_createCache() ); $part->setCharset('utf-8'); } public function testSettingCharsetNotifiesHeaders() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->charsetChanged('utf-8') -> ignoring($headers) ); $part = $this->_createMimePart($headers, $this->_createEncoder(), $this->_createCache() ); $part->setCharset('utf-8'); } public function testSettingCharsetNotifiesChildren() { $child = $this->_createChild(0, '', false); $this->_checking(Expectations::create() -> one($child)->charsetChanged('windows-874') -> ignoring($child) ); $part = $this->_createMimePart($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $part->setChildren(array($child)); $part->setCharset('windows-874'); } public function testCharsetChangeUpdatesCharset() { $cType = $this->_createHeader('Content-Type', 'text/plain', array('charset' => 'iso-8859-1'), false ); $this->_checking(Expectations::create() -> one($cType)->setParameter('charset', 'utf-8') -> ignoring($cType) ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $part->charsetChanged('utf-8'); } public function testSettingCharsetClearsCache() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> ignoring($headers)->toString() -> returns( "Content-Type: text/plain; charset=utf-8\r\n" ) -> ignoring($headers) ); $cache = $this->_createCache(false); $this->_checking(Expectations::create() -> one($cache)->clearKey(any(), 'body') -> ignoring($cache) ); $entity = $this->_createEntity($headers, $this->_createEncoder(), $cache ); $entity->setBody("blah\r\nblah!"); $entity->toString(); $entity->setCharset('iso-2022'); } public function testFormatIsReturnedFromHeader() { /* -- RFC 3676. */ $cType = $this->_createHeader('Content-Type', 'text/plain', array('format' => 'flowed') ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('flowed', $part->getFormat()); } public function testFormatIsSetInHeader() { $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false); $this->_checking(Expectations::create() -> one($cType)->setParameter('format', 'fixed') -> ignoring($cType) ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $part->setFormat('fixed'); } public function testDelSpIsReturnedFromHeader() { /* -- RFC 3676. */ $cType = $this->_createHeader('Content-Type', 'text/plain', array('delsp' => 'no') ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $this->assertIdentical(false, $part->getDelSp()); } public function testDelSpIsSetInHeader() { $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false); $this->_checking(Expectations::create() -> one($cType)->setParameter('delsp', 'yes') -> ignoring($cType) ); $part = $this->_createMimePart($this->_createHeaderSet(array( 'Content-Type' => $cType)), $this->_createEncoder(), $this->_createCache() ); $part->setDelSp(true); } public function testFluidInterface() { $part = $this->_createMimePart($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertSame($part, $part ->setContentType('text/plain') ->setEncoder($this->_createEncoder()) ->setId('foo@bar') ->setDescription('my description') ->setMaxLineLength(998) ->setBody('xx') ->setBoundary('xyz') ->setChildren(array()) ->setCharset('utf-8') ->setFormat('flowed') ->setDelSp(true) ); } // -- Private helpers //abstract protected function _createEntity($headers, $encoder, $cache) { return $this->_createMimePart($headers, $encoder, $cache); } protected function _createMimePart($headers, $encoder, $cache) { return new Swift_Mime_MimePart($headers, $encoder, $cache, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php100644 0 0 13102 12000050367 21316 0ustar 0 0 _factory = $this->_createFactory(); } public function testMailboxHeaderIsCorrectType() { $header = $this->_factory->createMailboxHeader('X-Foo'); $this->assertIsA($header, 'Swift_Mime_Headers_MailboxHeader'); } public function testMailboxHeaderHasCorrectName() { $header = $this->_factory->createMailboxHeader('X-Foo'); $this->assertEqual('X-Foo', $header->getFieldName()); } public function testMailboxHeaderHasCorrectModel() { $header = $this->_factory->createMailboxHeader('X-Foo', array('foo@bar'=>'FooBar') ); $this->assertEqual(array('foo@bar'=>'FooBar'), $header->getFieldBodyModel()); } public function testDateHeaderHasCorrectType() { $header = $this->_factory->createDateHeader('X-Date'); $this->assertIsA($header, 'Swift_Mime_Headers_DateHeader'); } public function testDateHeaderHasCorrectName() { $header = $this->_factory->createDateHeader('X-Date'); $this->assertEqual('X-Date', $header->getFieldName()); } public function testDateHeaderHasCorrectModel() { $header = $this->_factory->createDateHeader('X-Date', 123); $this->assertEqual(123, $header->getFieldBodyModel()); } public function testTextHeaderHasCorrectType() { $header = $this->_factory->createTextHeader('X-Foo'); $this->assertIsA($header, 'Swift_Mime_Headers_UnstructuredHeader'); } public function testTextHeaderHasCorrectName() { $header = $this->_factory->createTextHeader('X-Foo'); $this->assertEqual('X-Foo', $header->getFieldName()); } public function testTextHeaderHasCorrectModel() { $header = $this->_factory->createTextHeader('X-Foo', 'bar'); $this->assertEqual('bar', $header->getFieldBodyModel()); } public function testParameterizedHeaderHasCorrectType() { $header = $this->_factory->createParameterizedHeader('X-Foo'); $this->assertIsA($header, 'Swift_Mime_Headers_ParameterizedHeader'); } public function testParameterizedHeaderHasCorrectName() { $header = $this->_factory->createParameterizedHeader('X-Foo'); $this->assertEqual('X-Foo', $header->getFieldName()); } public function testParameterizedHeaderHasCorrectModel() { $header = $this->_factory->createParameterizedHeader('X-Foo', 'bar'); $this->assertEqual('bar', $header->getFieldBodyModel()); } public function testParameterizedHeaderHasCorrectParams() { $header = $this->_factory->createParameterizedHeader('X-Foo', 'bar', array('zip' => 'button') ); $this->assertEqual(array('zip'=>'button'), $header->getParameters()); } public function testIdHeaderHasCorrectType() { $header = $this->_factory->createIdHeader('X-ID'); $this->assertIsA($header, 'Swift_Mime_Headers_IdentificationHeader'); } public function testIdHeaderHasCorrectName() { $header = $this->_factory->createIdHeader('X-ID'); $this->assertEqual('X-ID', $header->getFieldName()); } public function testIdHeaderHasCorrectModel() { $header = $this->_factory->createIdHeader('X-ID', 'xyz@abc'); $this->assertEqual(array('xyz@abc'), $header->getFieldBodyModel()); } public function testPathHeaderHasCorrectType() { $header = $this->_factory->createPathHeader('X-Path'); $this->assertIsA($header, 'Swift_Mime_Headers_PathHeader'); } public function testPathHeaderHasCorrectName() { $header = $this->_factory->createPathHeader('X-Path'); $this->assertEqual('X-Path', $header->getFieldName()); } public function testPathHeaderHasCorrectModel() { $header = $this->_factory->createPathHeader('X-Path', 'foo@bar'); $this->assertEqual('foo@bar', $header->getFieldBodyModel()); } public function testCharsetChangeNotificationNotifiesEncoders() { $encoder = $this->_createHeaderEncoder(false); $paramEncoder = $this->_createParamEncoder(false); $factory = $this->_createFactory($encoder, $paramEncoder); $this->_checking(Expectations::create() -> one($encoder)->charsetChanged('utf-8') -> one($paramEncoder)->charsetChanged('utf-8') -> ignoring($encoder) -> ignoring($paramEncoder) ); $factory->charsetChanged('utf-8'); } // -- Creation methods private function _createFactory($encoder = null, $paramEncoder = null) { return new Swift_Mime_SimpleHeaderFactory( $encoder ? $encoder : $this->_createHeaderEncoder(), $paramEncoder ? $paramEncoder : $this->_createParamEncoder(), new Swift_Mime_Grammar() ); } private function _createHeaderEncoder($stub = true) { return $stub ? $this->_stub('Swift_Mime_HeaderEncoder') : $this->_mock('Swift_Mime_HeaderEncoder'); } private function _createParamEncoder($stub = true) { return $stub ? $this->_stub('Swift_Encoder') : $this->_mock('Swift_Encoder'); } } Swift-4.2.1/tests/unit/Swift/Mime/SimpleHeaderSetTest.php100644 0 0 60620 12000050367 20451 0ustar 0 0 _createFactory(); $this->_checking(Expectations::create() -> one($factory)->createMailboxHeader('From', array('person@domain'=>'Person')) -> returns($this->_createHeader('From')) ); $set = $this->_createSet($factory); $set->addMailboxHeader('From', array('person@domain'=>'Person')); } public function testAddDateHeaderDelegatesToFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createDateHeader('Date', 1234) -> returns($this->_createHeader('Date')) ); $set = $this->_createSet($factory); $set->addDateHeader('Date', 1234); } public function testAddTextHeaderDelegatesToFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('Subject', 'some text') -> returns($this->_createHeader('Subject')) ); $set = $this->_createSet($factory); $set->addTextHeader('Subject', 'some text'); } public function testAddParameterizedHeaderDelegatesToFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createParameterizedHeader( 'Content-Type', 'text/plain', array('charset'=>'utf-8') ) -> returns($this->_createHeader('Content-Type')) ); $set = $this->_createSet($factory); $set->addParameterizedHeader('Content-Type', 'text/plain', array('charset'=>'utf-8') ); } public function testAddIdHeaderDelegatesToFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createIdHeader('Message-ID', 'some@id') -> returns($this->_createHeader('Message-ID')) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); } public function testAddPathHeaderDelegatesToFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createPathHeader('Return-Path', 'some@path') -> returns($this->_createHeader('Return-Path')) ); $set = $this->_createSet($factory); $set->addPathHeader('Return-Path', 'some@path'); } public function testHasReturnsFalseWhenNoHeaders() { $set = $this->_createSet($this->_createFactory()); $this->assertFalse($set->has('Some-Header')); } public function testAddedMailboxHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createMailboxHeader('From', array('person@domain'=>'Person')) -> returns($this->_createHeader('From')) ); $set = $this->_createSet($factory); $set->addMailboxHeader('From', array('person@domain'=>'Person')); $this->assertTrue($set->has('From')); } public function testAddedDateHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createDateHeader('Date', 1234) -> returns($this->_createHeader('Date')) ); $set = $this->_createSet($factory); $set->addDateHeader('Date', 1234); $this->assertTrue($set->has('Date')); } public function testAddedTextHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createTextHeader('Subject', 'some text') -> returns($this->_createHeader('Subject')) ); $set = $this->_createSet($factory); $set->addTextHeader('Subject', 'some text'); $this->assertTrue($set->has('Subject')); } public function testAddedParameterizedHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createParameterizedHeader( 'Content-Type', 'text/plain', array('charset'=>'utf-8') ) -> returns($this->_createHeader('Content-Type')) ); $set = $this->_createSet($factory); $set->addParameterizedHeader('Content-Type', 'text/plain', array('charset'=>'utf-8') ); $this->assertTrue($set->has('Content-Type')); } public function testAddedIdHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($this->_createHeader('Message-ID')) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertTrue($set->has('Message-ID')); } public function testAddedPathHeaderIsSeenByHas() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createPathHeader('Return-Path', 'some@path') -> returns($this->_createHeader('Return-Path')) ); $set = $this->_createSet($factory); $set->addPathHeader('Return-Path', 'some@path'); $this->assertTrue($set->has('Return-Path')); } public function testNewlySetHeaderIsSeenByHas() { $factory = $this->_createFactory(); $header = $this->_createHeader('X-Foo', 'bar'); $set = $this->_createSet($factory); $set->set($header); $this->assertTrue($set->has('X-Foo')); } public function testHasCanAcceptOffset() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($this->_createHeader('Message-ID')) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertTrue($set->has('Message-ID', 0)); } public function testHasWithIllegalOffsetReturnsFalse() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($this->_createHeader('Message-ID')) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertFalse($set->has('Message-ID', 1)); } public function testHasCanDistinguishMultipleHeaders() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($this->_createHeader('Message-ID')) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($this->_createHeader('Message-ID')) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $this->assertTrue($set->has('Message-ID', 1)); } public function testGetWithUnspecifiedOffset() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertSame($header, $set->get('Message-ID')); } public function testGetWithSpeiciedOffset() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Message-ID'); $header2 = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($header1) -> ignoring($factory)->createIdHeader('Message-ID', 'more@id') -> returns($header2) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $set->addIdHeader('Message-ID', 'more@id'); $this->assertSame($header1, $set->get('Message-ID', 1)); } public function testGetReturnsNullIfHeaderNotSet() { $set = $this->_createSet($this->_createFactory()); $this->assertNull($set->get('Message-ID', 99)); } public function testGetAllReturnsAllHeadersMatchingName() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Message-ID'); $header2 = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($header1) -> ignoring($factory)->createIdHeader('Message-ID', 'more@id') -> returns($header2) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $set->addIdHeader('Message-ID', 'more@id'); $this->assertEqual(array($header0, $header1, $header2), $set->getAll('Message-ID') ); } public function testGetAllReturnsAllHeadersIfNoArguments() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Subject'); $header2 = $this->_createHeader('To'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Subject', 'thing') -> returns($header1) -> ignoring($factory)->createIdHeader('To', 'person@example.org') -> returns($header2) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Subject', 'thing'); $set->addIdHeader('To', 'person@example.org'); $this->assertEqual(array($header0, $header1, $header2), $set->getAll() ); } public function testGetAllReturnsEmptyArrayIfNoneSet() { $set = $this->_createSet($this->_createFactory()); $this->assertEqual(array(), $set->getAll('Received')); } public function testRemoveWithUnspecifiedOffset() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->remove('Message-ID'); $this->assertFalse($set->has('Message-ID')); } public function testRemoveWithSpecifiedIndexRemovesHeader() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($header1) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $set->remove('Message-ID', 1); $this->assertFalse($set->has('Message-ID', 1)); } public function testRemoveWithSpecifiedIndexLeavesOtherHeaders() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($header1) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $set->remove('Message-ID', 1); $this->assertTrue($set->has('Message-ID', 0)); } public function testRemoveWithInvalidOffsetDoesNothing() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->remove('Message-ID', 50); $this->assertTrue($set->has('Message-ID')); } public function testRemoveAllRemovesAllHeadersWithName() { $header0 = $this->_createHeader('Message-ID'); $header1 = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header0) -> ignoring($factory)->createIdHeader('Message-ID', 'other@id') -> returns($header1) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->addIdHeader('Message-ID', 'other@id'); $set->removeAll('Message-ID'); $this->assertFalse($set->has('Message-ID', 0)); $this->assertFalse($set->has('Message-ID', 1)); } public function testHasIsNotCaseSensitive() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertTrue($set->has('message-id')); } public function testGetIsNotCaseSensitive() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertSame($header, $set->get('message-id')); } public function testGetAllIsNotCaseSensitive() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $this->assertEqual(array($header), $set->getAll('message-id')); } public function testRemoveIsNotCaseSensitive() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->remove('message-id'); $this->assertFalse($set->has('Message-ID')); } public function testRemoveAllIsNotCaseSensitive() { $header = $this->_createHeader('Message-ID'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createIdHeader('Message-ID', 'some@id') -> returns($header) ); $set = $this->_createSet($factory); $set->addIdHeader('Message-ID', 'some@id'); $set->removeAll('message-id'); $this->assertFalse($set->has('Message-ID')); } public function testNewInstance() { $set = $this->_createSet($this->_createFactory()); $instance = $set->newInstance(); $this->assertIsA($instance, 'Swift_Mime_HeaderSet'); } public function testToStringJoinsHeadersTogether() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('Foo', 'bar') -> returns($this->_createHeader('Foo', 'bar')) -> one($factory)->createTextHeader('Zip', 'buttons') -> returns($this->_createHeader('Zip', 'buttons')) ); $set = $this->_createSet($factory); $set->addTextHeader('Foo', 'bar'); $set->addTextHeader('Zip', 'buttons'); $this->assertEqual( "Foo: bar\r\n" . "Zip: buttons\r\n", $set->toString() ); } public function testHeadersWithoutBodiesAreNotDisplayed() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('Foo', 'bar') -> returns($this->_createHeader('Foo', 'bar')) -> one($factory)->createTextHeader('Zip', '') -> returns($this->_createHeader('Zip', '')) ); $set = $this->_createSet($factory); $set->addTextHeader('Foo', 'bar'); $set->addTextHeader('Zip', ''); $this->assertEqual( "Foo: bar\r\n", $set->toString() ); } public function testHeadersWithoutBodiesCanBeForcedToDisplay() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('Foo', '') -> returns($this->_createHeader('Foo', '')) -> one($factory)->createTextHeader('Zip', '') -> returns($this->_createHeader('Zip', '')) ); $set = $this->_createSet($factory); $set->addTextHeader('Foo', ''); $set->addTextHeader('Zip', ''); $set->setAlwaysDisplayed(array('Foo', 'Zip')); $this->assertEqual( "Foo: \r\n" . "Zip: \r\n", $set->toString() ); } public function testHeaderSequencesCanBeSpecified() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('First', 'one') -> returns($this->_createHeader('First', 'one')) -> one($factory)->createTextHeader('Second', 'two') -> returns($this->_createHeader('Second', 'two')) -> one($factory)->createTextHeader('Third', 'three') -> returns($this->_createHeader('Third', 'three')) ); $set = $this->_createSet($factory); $set->addTextHeader('Third', 'three'); $set->addTextHeader('First', 'one'); $set->addTextHeader('Second', 'two'); $set->defineOrdering(array('First', 'Second', 'Third')); $this->assertEqual( "First: one\r\n" . "Second: two\r\n" . "Third: three\r\n", $set->toString() ); } public function testUnsortedHeadersAppearAtEnd() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createTextHeader('First', 'one') -> returns($this->_createHeader('First', 'one')) -> one($factory)->createTextHeader('Second', 'two') -> returns($this->_createHeader('Second', 'two')) -> one($factory)->createTextHeader('Third', 'three') -> returns($this->_createHeader('Third', 'three')) -> one($factory)->createTextHeader('Fourth', 'four') -> returns($this->_createHeader('Fourth', 'four')) -> one($factory)->createTextHeader('Fifth', 'five') -> returns($this->_createHeader('Fifth', 'five')) ); $set = $this->_createSet($factory); $set->addTextHeader('Fourth', 'four'); $set->addTextHeader('Fifth', 'five'); $set->addTextHeader('Third', 'three'); $set->addTextHeader('First', 'one'); $set->addTextHeader('Second', 'two'); $set->defineOrdering(array('First', 'Second', 'Third')); $this->assertEqual( "First: one\r\n" . "Second: two\r\n" . "Third: three\r\n" . "Fourth: four\r\n" . "Fifth: five\r\n", $set->toString() ); } public function testSettingCharsetNotifiesAlreadyExistingHeaders() { $subject = $this->_createHeader('Subject', 'some text'); $xHeader = $this->_createHeader('X-Header', 'some text'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createTextHeader('Subject', 'some text') -> returns($subject) -> ignoring($factory)->createTextHeader('X-Header', 'some text') -> returns($xHeader) -> ignoring($factory) -> one($subject)->setCharset('utf-8') -> one($xHeader)->setCharset('utf-8') ); $set = $this->_createSet($factory); $set->addTextHeader('Subject', 'some text'); $set->addTextHeader('X-Header', 'some text'); $set->setCharset('utf-8'); } public function testCharsetChangeNotifiesAlreadyExistingHeaders() { $subject = $this->_createHeader('Subject', 'some text'); $xHeader = $this->_createHeader('X-Header', 'some text'); $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> ignoring($factory)->createTextHeader('Subject', 'some text') -> returns($subject) -> ignoring($factory)->createTextHeader('X-Header', 'some text') -> returns($xHeader) -> ignoring($factory) -> one($subject)->setCharset('utf-8') -> one($xHeader)->setCharset('utf-8') ); $set = $this->_createSet($factory); $set->addTextHeader('Subject', 'some text'); $set->addTextHeader('X-Header', 'some text'); $set->charsetChanged('utf-8'); } public function testCharsetChangeNotifiesFactory() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->charsetChanged('utf-8') -> ignoring($factory) ); $set = $this->_createSet($factory); $set->setCharset('utf-8'); } // -- Creation methods private function _createSet($factory) { return new Swift_Mime_SimpleHeaderSet($factory); } private function _createFactory() { return $this->_mock('Swift_Mime_HeaderFactory'); } private function _createHeader($name, $body = '') { $header = $this->_mock('Swift_Mime_Header'); $this->_checking(Expectations::create() -> ignoring($header)->getFieldName() -> returns($name) -> ignoring($header)->toString() -> returns(sprintf("%s: %s\r\n", $name, $body)) -> ignoring($header)->getFieldBody() -> returns($body) ); return $header; } } Swift-4.2.1/tests/unit/Swift/Mime/SimpleMessageTest.php100644 0 0 67147 12000050367 20204 0ustar 0 0 _createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual( Swift_Mime_MimeEntity::LEVEL_TOP, $message->getNestingLevel() ); } public function testDateIsReturnedFromHeader() { $date = $this->_createHeader('Date', 123); $message = $this->_createMessage( $this->_createHeaderSet(array('Date' => $date)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(123, $message->getDate()); } public function testDateIsSetInHeader() { $date = $this->_createHeader('Date', 123, array(), false); $this->_checking(Expectations::create() -> one($date)->setFieldBodyModel(1234) -> ignoring($date) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Date' => $date)), $this->_createEncoder(), $this->_createCache() ); $message->setDate(1234); } public function testDateHeaderIsCreatedIfNonePresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addDateHeader('Date', 1234) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setDate(1234); } public function testDateHeaderIsAddedDuringConstruction() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addDateHeader('Date', pattern('/^[0-9]+$/D')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); } public function testIdIsReturnedFromHeader() { /* -- RFC 2045, 7. In constructing a high-level user agent, it may be desirable to allow one body to make reference to another. Accordingly, bodies may be labelled using the "Content-ID" header field, which is syntactically identical to the "Message-ID" header field */ $messageId = $this->_createHeader('Message-ID', 'a@b'); $message = $this->_createMessage( $this->_createHeaderSet(array('Message-ID' => $messageId)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('a@b', $message->getId()); } public function testIdIsSetInHeader() { $messageId = $this->_createHeader('Message-ID', 'a@b', array(), false); $this->_checking(Expectations::create() -> one($messageId)->setFieldBodyModel('x@y') -> ignoring($messageId) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Message-ID' => $messageId)), $this->_createEncoder(), $this->_createCache() ); $message->setId('x@y'); } public function testIdIsAutoGenerated() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addIdHeader('Message-ID', pattern('/^.*?@.*?$/D')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); } public function testSubjectIsReturnedFromHeader() { /* -- RFC 2822, 3.6.5. */ $subject = $this->_createHeader('Subject', 'example subject'); $message = $this->_createMessage( $this->_createHeaderSet(array('Subject' => $subject)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('example subject', $message->getSubject()); } public function testSubjectIsSetInHeader() { $subject = $this->_createHeader('Subject', '', array(), false); $this->_checking(Expectations::create() -> one($subject)->setFieldBodyModel('foo') -> ignoring($subject) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Subject' => $subject)), $this->_createEncoder(), $this->_createCache() ); $message->setSubject('foo'); } public function testSubjectHeaderIsCreatedIfNotPresent() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addTextHeader('Subject', 'example subject') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setSubject('example subject'); } public function testReturnPathIsReturnedFromHeader() { /* -- RFC 2822, 3.6.7. */ $path = $this->_createHeader('Return-Path', 'bounces@domain'); $message = $this->_createMessage( $this->_createHeaderSet(array('Return-Path' => $path)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('bounces@domain', $message->getReturnPath()); } public function testReturnPathIsSetInHeader() { $path = $this->_createHeader('Return-Path', '', array(), false); $this->_checking(Expectations::create() -> one($path)->setFieldBodyModel('bounces@domain') -> ignoring($path) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Return-Path' => $path)), $this->_createEncoder(), $this->_createCache() ); $message->setReturnPath('bounces@domain'); } public function testReturnPathHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addPathHeader('Return-Path', 'bounces@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setReturnPath('bounces@domain'); } public function testSenderIsReturnedFromHeader() { /* -- RFC 2822, 3.6.2. */ $sender = $this->_createHeader('Sender', array('sender@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('Sender' => $sender)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('sender@domain'=>'Name'), $message->getSender()); } public function testSenderIsSetInHeader() { $sender = $this->_createHeader('Sender', array('sender@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($sender)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($sender) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Sender' => $sender)), $this->_createEncoder(), $this->_createCache() ); $message->setSender(array('other@domain'=>'Other')); } public function testSenderHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Sender', (array) 'sender@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setSender('sender@domain'); } public function testNameCanBeUsedInSenderHeader() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Sender', array('sender@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setSender('sender@domain', 'Name'); } public function testFromIsReturnedFromHeader() { /* -- RFC 2822, 3.6.2. */ $from = $this->_createHeader('From', array('from@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('From' => $from)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('from@domain'=>'Name'), $message->getFrom()); } public function testFromIsSetInHeader() { $from = $this->_createHeader('From', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($from)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($from) ); $message = $this->_createMessage( $this->_createHeaderSet(array('From' => $from)), $this->_createEncoder(), $this->_createCache() ); $message->setFrom(array('other@domain'=>'Other')); } public function testFromIsAddedToHeadersDuringAddFrom() { $from = $this->_createHeader('From', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($from)->setFieldBodyModel(array('from@domain'=>'Name', 'other@domain'=>'Other')) -> ignoring($from) ); $message = $this->_createMessage( $this->_createHeaderSet(array('From' => $from)), $this->_createEncoder(), $this->_createCache() ); $message->addFrom('other@domain', 'Other'); } public function testFromHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('From', (array) 'from@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setFrom('from@domain'); } public function testPersonalNameCanBeUsedInFromAddress() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('From', array('from@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setFrom('from@domain', 'Name'); } public function testReplyToIsReturnedFromHeader() { /* -- RFC 2822, 3.6.2. */ $reply = $this->_createHeader('Reply-To', array('reply@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('Reply-To' => $reply)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('reply@domain'=>'Name'), $message->getReplyTo()); } public function testReplyToIsSetInHeader() { $reply = $this->_createHeader('Reply-To', array('reply@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($reply)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($reply) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Reply-To' => $reply)), $this->_createEncoder(), $this->_createCache() ); $message->setReplyTo(array('other@domain'=>'Other')); } public function testReplyToIsAddedToHeadersDuringAddReplyTo() { $replyTo = $this->_createHeader('Reply-To', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($replyTo)->setFieldBodyModel(array('from@domain'=>'Name', 'other@domain'=>'Other')) -> ignoring($replyTo) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Reply-To' => $replyTo)), $this->_createEncoder(), $this->_createCache() ); $message->addReplyTo('other@domain', 'Other'); } public function testReplyToHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Reply-To', (array) 'reply@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setReplyTo('reply@domain'); } public function testNameCanBeUsedInReplyTo() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Reply-To', array('reply@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setReplyTo('reply@domain', 'Name'); } public function testToIsReturnedFromHeader() { /* -- RFC 2822, 3.6.3. */ $to = $this->_createHeader('To', array('to@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('To' => $to)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('to@domain'=>'Name'), $message->getTo()); } public function testToIsSetInHeader() { $to = $this->_createHeader('To', array('to@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($to)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($to) ); $message = $this->_createMessage( $this->_createHeaderSet(array('To' => $to)), $this->_createEncoder(), $this->_createCache() ); $message->setTo(array('other@domain'=>'Other')); } public function testToIsAddedToHeadersDuringAddTo() { $to = $this->_createHeader('To', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($to)->setFieldBodyModel(array('from@domain'=>'Name', 'other@domain'=>'Other')) -> ignoring($to) ); $message = $this->_createMessage( $this->_createHeaderSet(array('To' => $to)), $this->_createEncoder(), $this->_createCache() ); $message->addTo('other@domain', 'Other'); } public function testToHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('To', (array) 'to@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setTo('to@domain'); } public function testNameCanBeUsedInToHeader() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('To', array('to@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setTo('to@domain', 'Name'); } public function testCcIsReturnedFromHeader() { /* -- RFC 2822, 3.6.3. */ $cc = $this->_createHeader('Cc', array('cc@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('Cc' => $cc)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('cc@domain'=>'Name'), $message->getCc()); } public function testCcIsSetInHeader() { $cc = $this->_createHeader('Cc', array('cc@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($cc)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($cc) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Cc' => $cc)), $this->_createEncoder(), $this->_createCache() ); $message->setCc(array('other@domain'=>'Other')); } public function testCcIsAddedToHeadersDuringAddCc() { $cc = $this->_createHeader('Cc', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($cc)->setFieldBodyModel(array('from@domain'=>'Name', 'other@domain'=>'Other')) -> ignoring($cc) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Cc' => $cc)), $this->_createEncoder(), $this->_createCache() ); $message->addCc('other@domain', 'Other'); } public function testCcHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Cc', (array) 'cc@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setCc('cc@domain'); } public function testNameCanBeUsedInCcHeader() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Cc', array('cc@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setCc('cc@domain', 'Name'); } public function testBccIsReturnedFromHeader() { /* -- RFC 2822, 3.6.3. */ $bcc = $this->_createHeader('Bcc', array('bcc@domain'=>'Name')); $message = $this->_createMessage( $this->_createHeaderSet(array('Bcc' => $bcc)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('bcc@domain'=>'Name'), $message->getBcc()); } public function testBccIsSetInHeader() { $bcc = $this->_createHeader('Bcc', array('bcc@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($bcc)->setFieldBodyModel(array('other@domain'=>'Other')) -> ignoring($bcc) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Bcc' => $bcc)), $this->_createEncoder(), $this->_createCache() ); $message->setBcc(array('other@domain'=>'Other')); } public function testBccIsAddedToHeadersDuringAddBcc() { $bcc = $this->_createHeader('Bcc', array('from@domain'=>'Name'), array(), false ); $this->_checking(Expectations::create() -> one($bcc)->setFieldBodyModel(array('from@domain'=>'Name', 'other@domain'=>'Other')) -> ignoring($bcc) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Bcc' => $bcc)), $this->_createEncoder(), $this->_createCache() ); $message->addBcc('other@domain', 'Other'); } public function testBccHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Bcc', (array) 'bcc@domain') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setBcc('bcc@domain'); } public function testNameCanBeUsedInBcc() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader('Bcc', array('bcc@domain'=>'Name')) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setBcc('bcc@domain', 'Name'); } public function testPriorityIsReadFromHeader() { $prio = $this->_createHeader('X-Priority', '2 (High)'); $message = $this->_createMessage( $this->_createHeaderSet(array('X-Priority' => $prio)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(2, $message->getPriority()); } public function testPriorityIsSetInHeader() { $prio = $this->_createHeader('X-Priority', '2 (High)', array(), false); $this->_checking(Expectations::create() -> one($prio)->setFieldBodyModel('5 (Lowest)') -> ignoring($prio) ); $message = $this->_createMessage( $this->_createHeaderSet(array('X-Priority' => $prio)), $this->_createEncoder(), $this->_createCache() ); $message->setPriority(5); } public function testPriorityHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addTextHeader('X-Priority', '4 (Low)') -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setPriority(4); } public function testReadReceiptAddressReadFromHeader() { $rcpt = $this->_createHeader('Disposition-Notification-To', array('chris@swiftmailer.org'=>'Chris') ); $message = $this->_createMessage( $this->_createHeaderSet(array('Disposition-Notification-To' => $rcpt)), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual(array('chris@swiftmailer.org'=>'Chris'), $message->getReadReceiptTo() ); } public function testReadReceiptIsSetInHeader() { $rcpt = $this->_createHeader('Disposition-Notification-To', array(), array(), false); $this->_checking(Expectations::create() -> one($rcpt)->setFieldBodyModel('mark@swiftmailer.org') -> ignoring($rcpt) ); $message = $this->_createMessage( $this->_createHeaderSet(array('Disposition-Notification-To' => $rcpt)), $this->_createEncoder(), $this->_createCache() ); $message->setReadReceiptTo('mark@swiftmailer.org'); } public function testReadReceiptHeaderIsAddedIfNoneSet() { $headers = $this->_createHeaderSet(array(), false); $this->_checking(Expectations::create() -> one($headers)->addMailboxHeader( 'Disposition-Notification-To', 'mark@swiftmailer.org' ) -> ignoring($headers) ); $message = $this->_createMessage($headers, $this->_createEncoder(), $this->_createCache() ); $message->setReadReceiptTo('mark@swiftmailer.org'); } public function testChildrenCanBeAttached() { $child1 = $this->_createChild(); $child2 = $this->_createChild(); $message = $this->_createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $message->attach($child1); $message->attach($child2); $this->assertEqual(array($child1, $child2), $message->getChildren()); } public function testChildrenCanBeDetached() { $child1 = $this->_createChild(); $child2 = $this->_createChild(); $message = $this->_createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $message->attach($child1); $message->attach($child2); $message->detach($child1); $this->assertEqual(array($child2), $message->getChildren()); } public function testEmbedAttachesChild() { $child = $this->_createChild(); $message = $this->_createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $message->embed($child); $this->assertEqual(array($child), $message->getChildren()); } public function testEmbedReturnsValidCid() { $child = $this->_createChild(Swift_Mime_MimeEntity::LEVEL_RELATED, '', false ); $this->_checking(Expectations::create() -> ignoring($child)->getId() -> returns('foo@bar') -> ignoring($child) ); $message = $this->_createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertEqual('cid:foo@bar', $message->embed($child)); } public function testFluidInterface() { $child = $this->_createChild(); $message = $this->_createMessage($this->_createHeaderSet(), $this->_createEncoder(), $this->_createCache() ); $this->assertSame($message, $message ->setContentType('text/plain') ->setEncoder($this->_createEncoder()) ->setId('foo@bar') ->setDescription('my description') ->setMaxLineLength(998) ->setBody('xx') ->setBoundary('xyz') ->setChildren(array()) ->setCharset('iso-8859-1') ->setFormat('flowed') ->setDelSp(false) ->setSubject('subj') ->setDate(123) ->setReturnPath('foo@bar') ->setSender('foo@bar') ->setFrom(array('x@y' => 'XY')) ->setReplyTo(array('ab@cd' => 'ABCD')) ->setTo(array('chris@site.tld', 'mark@site.tld')) ->setCc('john@somewhere.tld') ->setBcc(array('one@site', 'two@site' => 'Two')) ->setPriority(4) ->setReadReceiptTo('a@b') ->attach($child) ->detach($child) ); } // -- Private helpers //abstract protected function _createEntity($headers, $encoder, $cache) { return $this->_createMessage($headers, $encoder, $cache); } protected function _createMimePart($headers, $encoder, $cache) { return $this->_createMessage($headers, $encoder, $cache); } private function _createMessage($headers, $encoder, $cache) { return new Swift_Mime_SimpleMessage($headers, $encoder, $cache, new Swift_Mime_Grammar()); } } Swift-4.2.1/tests/unit/Swift/Mime/SimpleMimeEntityTest.php100644 0 0 703 12000050367 20625 0ustar 0 0 assertEqual(10, $plugin->getThreshold()); $plugin->setThreshold(100); $this->assertEqual(100, $plugin->getThreshold()); } public function testSleepTimeCanBeSetAndFetched() { $plugin = new Swift_Plugins_AntiFloodPlugin(10, 5); $this->assertEqual(5, $plugin->getSleepTime()); $plugin->setSleepTime(1); $this->assertEqual(1, $plugin->getSleepTime()); } public function testPluginStopsConnectionAfterThreshold() { $transport = $this->_createTransport(); $evt = $this->_createSendEvent($transport); $this->_checking(Expectations::create() -> one($transport)->start() -> one($transport)->stop() -> ignoring($transport) ); $plugin = new Swift_Plugins_AntiFloodPlugin(10); for ($i = 0; $i < 12; $i++) { $plugin->sendPerformed($evt); } } public function testPluginCanStopAndStartMultipleTimes() { $transport = $this->_createTransport(); $evt = $this->_createSendEvent($transport); $this->_checking(Expectations::create() -> exactly(5)->of($transport)->start() -> exactly(5)->of($transport)->stop() -> ignoring($transport) ); $plugin = new Swift_Plugins_AntiFloodPlugin(2); for ($i = 0; $i < 11; $i++) { $plugin->sendPerformed($evt); } } public function testPluginCanSleepDuringRestart() { $sleeper = $this->_createSleeper(); $transport = $this->_createTransport(); $evt = $this->_createSendEvent($transport); $this->_checking(Expectations::create() -> one($sleeper)->sleep(10) -> one($transport)->start() -> one($transport)->stop() -> ignoring($transport) ); $plugin = new Swift_Plugins_AntiFloodPlugin(99, 10, $sleeper); for ($i = 0; $i < 101; $i++) { $plugin->sendPerformed($evt); } } // -- Creation Methods private function _createTransport() { return $this->_mock('Swift_Transport'); } private function _createSendEvent($transport) { $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getSource() -> returns($transport) -> ignoring($evt)->getTransport() -> returns($transport) ); return $evt; } private function _createSleeper() { return $this->_mock('Swift_Plugins_Sleeper'); } } Swift-4.2.1/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php100644 0 0 10031 12000050367 22607 0ustar 0 0 _monitor = new Swift_Plugins_BandwidthMonitorPlugin(); } public function testBytesOutIncreasesAccordingToMessageLength() { $message = $this->_createMessageWithByteCount(6); $evt = $this->_createSendEvent($message); $this->assertEqual(0, $this->_monitor->getBytesOut()); $this->_monitor->sendPerformed($evt); $this->assertEqual(6, $this->_monitor->getBytesOut()); $this->_monitor->sendPerformed($evt); $this->assertEqual(12, $this->_monitor->getBytesOut()); } public function testBytesOutIncreasesWhenCommandsSent() { $evt = $this->_createCommandEvent("RCPT TO: \r\n"); $this->assertEqual(0, $this->_monitor->getBytesOut()); $this->_monitor->commandSent($evt); $this->assertEqual(24, $this->_monitor->getBytesOut()); $this->_monitor->commandSent($evt); $this->assertEqual(48, $this->_monitor->getBytesOut()); } public function testBytesInIncreasesWhenResponsesReceived() { $evt = $this->_createResponseEvent("250 Ok\r\n"); $this->assertEqual(0, $this->_monitor->getBytesIn()); $this->_monitor->responseReceived($evt); $this->assertEqual(8, $this->_monitor->getBytesIn()); $this->_monitor->responseReceived($evt); $this->assertEqual(16, $this->_monitor->getBytesIn()); } public function testCountersCanBeReset() { $evt = $this->_createResponseEvent("250 Ok\r\n"); $this->assertEqual(0, $this->_monitor->getBytesIn()); $this->_monitor->responseReceived($evt); $this->assertEqual(8, $this->_monitor->getBytesIn()); $this->_monitor->responseReceived($evt); $this->assertEqual(16, $this->_monitor->getBytesIn()); $evt = $this->_createCommandEvent("RCPT TO: \r\n"); $this->assertEqual(0, $this->_monitor->getBytesOut()); $this->_monitor->commandSent($evt); $this->assertEqual(24, $this->_monitor->getBytesOut()); $this->_monitor->commandSent($evt); $this->assertEqual(48, $this->_monitor->getBytesOut()); $this->_monitor->reset(); $this->assertEqual(0, $this->_monitor->getBytesOut()); $this->assertEqual(0, $this->_monitor->getBytesIn()); } // -- Creation Methods private function _createSendEvent($message) { $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getMessage() -> returns($message) ); return $evt; } private function _createCommandEvent($command) { $evt = $this->_mock('Swift_Events_CommandEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getCommand() -> returns($command) ); return $evt; } private function _createResponseEvent($response) { $evt = $this->_mock('Swift_Events_ResponseEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getResponse() -> returns($response) ); return $evt; } private function _createMessageWithByteCount($bytes) { $this->_bytes = $bytes; $msg = $this->_mock('Swift_Mime_Message'); $this->_checking(Expectations::create() -> ignoring($msg)->toByteStream(any()) -> calls(array($this, '_write')) ); return $msg; } private $_bytes = 0; public function _write($invocation) { $args = $invocation->getArguments(); $is = $args[0]; for ($i = 0; $i < $this->_bytes; ++$i) { $is->write('x'); } } }Swift-4.2.1/tests/unit/Swift/Plugins/DecoratorPluginTest.php100644 0 0 17563 12000050367 21276 0ustar 0 0 _createMessage( $this->_createHeaders(), array('zip@button.tld' => 'Zipathon'), array('chris.corbyn@swiftmailer.org' => 'Chris'), 'Subject', 'Hello {name}, you are customer #{id}' ); $this->_checking(Expectations::create() -> one($message)->setBody('Hello Zip, you are customer #456') -> ignoring($message) ); $plugin = $this->_createPlugin( array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456')) ); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } public function testReplacementsCanBeAppliedToSameMessageMultipleTimes() { $message = $this->_createMessage( $this->_createHeaders(), array('zip@button.tld' => 'Zipathon', 'foo@bar.tld' => 'Foo'), array('chris.corbyn@swiftmailer.org' => 'Chris'), 'Subject', 'Hello {name}, you are customer #{id}' ); $this->_checking(Expectations::create() -> one($message)->setBody('Hello Zip, you are customer #456') -> one($message)->setBody('Hello {name}, you are customer #{id}') -> one($message)->setBody('Hello Foo, you are customer #123') -> ignoring($message) ); $plugin = $this->_createPlugin( array( 'foo@bar.tld' => array('{name}' => 'Foo', '{id}' => '123'), 'zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456') ) ); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } public function testReplacementsCanBeMadeInHeaders() { $headers = $this->_createHeaders(array( $returnPathHeader = $this->_createHeader('Return-Path', 'foo-{id}@swiftmailer.org'), $toHeader = $this->_createHeader('Subject', 'A message for {name}!') )); $message = $this->_createMessage( $headers, array('zip@button.tld' => 'Zipathon'), array('chris.corbyn@swiftmailer.org' => 'Chris'), 'A message for {name}!', 'Hello {name}, you are customer #{id}' ); $this->_checking(Expectations::create() -> one($message)->setBody('Hello Zip, you are customer #456') -> one($toHeader)->setFieldBodyModel('A message for Zip!') -> one($returnPathHeader)->setFieldBodyModel('foo-456@swiftmailer.org') -> ignoring($message) -> ignoring($toHeader) -> ignoring($returnPathHeader) ); $plugin = $this->_createPlugin( array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456')) ); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } public function testReplacementsAreMadeOnSubparts() { $part1 = $this->_createPart('text/plain', 'Your name is {name}?', '1@x'); $part2 = $this->_createPart('text/html', 'Your name is {name}?', '2@x'); $message = $this->_createMessage( $this->_createHeaders(), array('zip@button.tld' => 'Zipathon'), array('chris.corbyn@swiftmailer.org' => 'Chris'), 'A message for {name}!', 'Subject' ); $this->_checking(Expectations::create() -> ignoring($message)->getChildren() -> returns(array($part1, $part2)) -> one($part1)->setBody('Your name is Zip?') -> one($part2)->setBody('Your name is Zip?') -> ignoring($part1) -> ignoring($part2) -> ignoring($message) ); $plugin = $this->_createPlugin( array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456')) ); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } public function testReplacementsCanBeTakenFromCustomReplacementsObject() { $message = $this->_createMessage( $this->_createHeaders(), array('foo@bar' => 'Foobar', 'zip@zap' => 'Zip zap'), array('chris.corbyn@swiftmailer.org' => 'Chris'), 'Subject', 'Something {a}' ); $replacements = $this->_createReplacements(); $this->_checking(Expectations::create() -> one($message)->setBody('Something b') -> one($message)->setBody('Something c') -> one($replacements)->getReplacementsFor('foo@bar') -> returns(array('{a}'=>'b')) -> one($replacements)->getReplacementsFor('zip@zap') -> returns(array('{a}'=>'c')) -> ignoring($message) ); $plugin = $this->_createPlugin($replacements); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } // -- Creation methods private function _createMessage($headers, $to = array(), $from = null, $subject = null, $body = null) { $message = $this->_mock('Swift_Mime_Message'); foreach ($to as $addr => $name) { $this->_checking(Expectations::create() -> one($message)->getTo() -> returns(array($addr => $name)) ); } $this->_checking(Expectations::create() -> allowing($message)->getHeaders() -> returns($headers) -> ignoring($message)->getFrom() -> returns($from) -> ignoring($message)->getSubject() -> returns($subject) -> ignoring($message)->getBody() -> returns($body) ); return $message; } private function _createPlugin($replacements) { return new Swift_Plugins_DecoratorPlugin($replacements); } private function _createReplacements() { return $this->_mock('Swift_Plugins_Decorator_Replacements'); } private function _createSendEvent(Swift_Mime_Message $message) { $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getMessage() -> returns($message) -> ignoring($evt) ); return $evt; } private function _createPart($type, $body, $id) { $part = $this->_mock('Swift_Mime_MimeEntity'); $this->_checking(Expectations::create() -> ignoring($part)->getContentType() -> returns($type) -> ignoring($part)->getBody() -> returns($body) -> ignoring($part)->getId() -> returns($id) ); return $part; } private function _createHeaders($headers = array()) { $set = $this->_mock('Swift_Mime_HeaderSet'); $this->_checking(Expectations::create() -> allowing($set)->getAll() -> returns($headers) -> ignoring($set) ); foreach ($headers as $header) { $set->set($header); } return $set; } private function _createHeader($name, $body = '') { $header = $this->_mock('Swift_Mime_Header'); $this->_checking(Expectations::create() -> ignoring($header)->getFieldName() -> returns($name) -> ignoring($header)->getFieldBodyModel() -> returns($body) ); return $header; } } Swift-4.2.1/tests/unit/Swift/Plugins/LoggerPluginTest.php100644 0 0 13337 12000050367 20566 0ustar 0 0 _createLogger(); $this->_checking(Expectations::create() -> one($logger)->add('foo') ); $plugin = $this->_createPlugin($logger); $plugin->add('foo'); } public function testLoggerDelegatesDumpingEntries() { $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->dump() -> returns('foobar') ); $plugin = $this->_createPlugin($logger); $this->assertEqual('foobar', $plugin->dump()); } public function testLoggerDelegatesClearingEntries() { $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->clear() ); $plugin = $this->_createPlugin($logger); $plugin->clear(); } public function testCommandIsSentToLogger() { $evt = $this->_createCommandEvent("foo\r\n"); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(pattern('~foo\r\n~')) ); $plugin = $this->_createPlugin($logger); $plugin->commandSent($evt); } public function testResponseIsSentToLogger() { $evt = $this->_createResponseEvent("354 Go ahead\r\n"); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(pattern('~354 Go ahead\r\n~')) ); $plugin = $this->_createPlugin($logger); $plugin->responseReceived($evt); } public function testTransportBeforeStartChangeIsSentToLogger() { $evt = $this->_createTransportChangeEvent(); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(any()) ); $plugin = $this->_createPlugin($logger); $plugin->beforeTransportStarted($evt); } public function testTransportStartChangeIsSentToLogger() { $evt = $this->_createTransportChangeEvent(); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(any()) ); $plugin = $this->_createPlugin($logger); $plugin->transportStarted($evt); } public function testTransportStopChangeIsSentToLogger() { $evt = $this->_createTransportChangeEvent(); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(any()) ); $plugin = $this->_createPlugin($logger); $plugin->transportStopped($evt); } public function testTransportBeforeStopChangeIsSentToLogger() { $evt = $this->_createTransportChangeEvent(); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(any()) ); $plugin = $this->_createPlugin($logger); $plugin->beforeTransportStopped($evt); } public function testExceptionsArePassedToDelegateAndLeftToBubbleUp() { $transport = $this->_createTransport(); $evt = $this->_createTransportExceptionEvent(); $logger = $this->_createLogger(); $this->_checking(Expectations::create() -> one($logger)->add(any()) -> allowing($logger) ); $plugin = $this->_createPlugin($logger); try { $plugin->exceptionThrown($evt); $this->fail('Exception should bubble up.'); } catch (Swift_TransportException $ex) { } } // -- Creation Methods private function _createLogger() { return $this->_mock('Swift_Plugins_Logger'); } private function _createPlugin($logger) { return new Swift_Plugins_LoggerPlugin($logger); } private function _createCommandEvent($command) { $evt = $this->_mock('Swift_Events_CommandEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getCommand() -> returns($command) -> ignoring($evt) ); return $evt; } private function _createResponseEvent($response) { $evt = $this->_mock('Swift_Events_ResponseEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getResponse() -> returns($response) -> ignoring($evt) ); return $evt; } private function _createTransport() { return $this->_mock('Swift_Transport'); } private function _createTransportChangeEvent() { $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getSource() -> returns($this->_createTransport()) -> ignoring($evt) ); return $evt; } private function _createTransportExceptionEvent() { $evt = $this->_mock('Swift_Events_TransportExceptionEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getException() -> returns(new Swift_TransportException('')) -> ignoring($evt) ); return $evt; } } Swift-4.2.1/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php100644 0 0 3776 12000050367 21776 0ustar 0 0 add(">> Foo\r\n"); $this->assertEqual(">> Foo\r\n", $logger->dump()); } public function testAddingMultipleEntriesDumpsMultipleLines() { $logger = new Swift_Plugins_Loggers_ArrayLogger(); $logger->add(">> FOO\r\n"); $logger->add("<< 502 That makes no sense\r\n"); $logger->add(">> RSET\r\n"); $logger->add("<< 250 OK\r\n"); $this->assertEqual( ">> FOO\r\n" . PHP_EOL . "<< 502 That makes no sense\r\n" . PHP_EOL . ">> RSET\r\n" . PHP_EOL . "<< 250 OK\r\n", $logger->dump() ); } public function testLogCanBeCleared() { $logger = new Swift_Plugins_Loggers_ArrayLogger(); $logger->add(">> FOO\r\n"); $logger->add("<< 502 That makes no sense\r\n"); $logger->add(">> RSET\r\n"); $logger->add("<< 250 OK\r\n"); $this->assertEqual( ">> FOO\r\n" . PHP_EOL . "<< 502 That makes no sense\r\n" . PHP_EOL . ">> RSET\r\n" . PHP_EOL . "<< 250 OK\r\n", $logger->dump() ); $logger->clear(); $this->assertEqual('', $logger->dump()); } public function testLengthCanBeTruncated() { $logger = new Swift_Plugins_Loggers_ArrayLogger(2); $logger->add(">> FOO\r\n"); $logger->add("<< 502 That makes no sense\r\n"); $logger->add(">> RSET\r\n"); $logger->add("<< 250 OK\r\n"); $this->assertEqual( ">> RSET\r\n" . PHP_EOL . "<< 250 OK\r\n", $logger->dump(), '%s: Log should be truncated to last 2 entries' ); } }Swift-4.2.1/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php100644 0 0 1400 12000050367 21554 0ustar 0 0 add(">> Foo"); $data = ob_get_clean(); $this->assertEqual(">> Foo" . PHP_EOL, $data); } public function testAddingEntryDumpsEscapedLineWithHtml() { $logger = new Swift_Plugins_Loggers_EchoLogger(true); ob_start(); $logger->add(">> Foo"); $data = ob_get_clean(); $this->assertEqual(">> Foo
" . PHP_EOL, $data); } }Swift-4.2.1/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php100644 0 0 6313 12000050367 22050 0ustar 0 0 _createConnection(); $plugin = $this->_createPlugin('pop.host.tld', 110); $plugin->setConnection($connection); $transport = $this->_createTransport(); $evt = $this->_createTransportChangeEvent($transport); $this->_checking(Expectations::create() -> one($connection)->connect() -> ignoring($connection) ); $plugin->beforeTransportStarted($evt); } public function testPluginDisconnectsFromPop3HostBeforeTransportStarts() { $connection = $this->_createConnection(); $plugin = $this->_createPlugin('pop.host.tld', 110); $plugin->setConnection($connection); $transport = $this->_createTransport(); $evt = $this->_createTransportChangeEvent($transport); $this->_checking(Expectations::create() -> one($connection)->disconnect() -> ignoring($connection) ); $plugin->beforeTransportStarted($evt); } public function testPluginDoesNotConnectToSmtpIfBoundToDifferentTransport() { $connection = $this->_createConnection(); $smtp = $this->_createTransport(); $plugin = $this->_createPlugin('pop.host.tld', 110); $plugin->setConnection($connection); $plugin->bindSmtp($smtp); $transport = $this->_createTransport(); $evt = $this->_createTransportChangeEvent($transport); $this->_checking(Expectations::create() -> never($connection) ); $plugin->beforeTransportStarted($evt); } public function testPluginCanBindToSpecificTransport() { $connection = $this->_createConnection(); $smtp = $this->_createTransport(); $plugin = $this->_createPlugin('pop.host.tld', 110); $plugin->setConnection($connection); $plugin->bindSmtp($smtp); $evt = $this->_createTransportChangeEvent($smtp); $this->_checking(Expectations::create() -> one($connection)->connect() -> ignoring($connection) ); $plugin->beforeTransportStarted($evt); } // -- Creation Methods private function _createTransport() { return $this->_mock('Swift_Transport'); } private function _createTransportChangeEvent($transport) { $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getSource() -> returns($transport) -> ignoring($evt)->getTransport() -> returns($transport) ); return $evt; } public function _createConnection() { return $this->_mock('Swift_Plugins_Pop_Pop3Connection'); } public function _createPlugin($host, $port, $crypto = null) { return new Swift_Plugins_PopBeforeSmtpPlugin($host, $port, $crypto); } } Swift-4.2.1/tests/unit/Swift/Plugins/RedirectingPluginTest.php100644 0 0 4322 12000050367 21560 0ustar 0 0 assertEqual('fabien@example.com', $plugin->getRecipient()); $plugin->setRecipient('chris@example.com'); $this->assertEqual('chris@example.com', $plugin->getRecipient()); } public function testPluginChangesRecipients() { $message = Swift_Message::newInstance() ->setSubject('...') ->setFrom(array('john@example.com' => 'John Doe')) ->setTo($to = array( 'fabien-to@example.com' => 'Fabien (To)', 'chris-to@example.com' => 'Chris (To)', )) ->setCc($cc = array( 'fabien-cc@example.com' => 'Fabien (Cc)', 'chris-cc@example.com' => 'Chris (Cc)', )) ->setBcc($bcc = array( 'fabien-bcc@example.com' => 'Fabien (Bcc)', 'chris-bcc@example.com' => 'Chris (Bcc)', )) ->setBody('...') ; $plugin = new Swift_Plugins_RedirectingPlugin('god@example.com'); $evt = $this->_createSendEvent($message); $plugin->beforeSendPerformed($evt); $this->assertEqual($message->getTo(), array('god@example.com' => '')); $this->assertEqual($message->getCc(), array()); $this->assertEqual($message->getBcc(), array()); $plugin->sendPerformed($evt); $this->assertEqual($message->getTo(), $to); $this->assertEqual($message->getCc(), $cc); $this->assertEqual($message->getBcc(), $bcc); } // -- Creation Methods private function _createSendEvent(Swift_Mime_Message $message) { $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getMessage() -> returns($message) -> ignoring($evt) ); return $evt; } } Swift-4.2.1/tests/unit/Swift/Plugins/ReporterPluginTest.php100644 0 0 10741 12000050367 21145 0ustar 0 0 _createMessage(); $evt = $this->_createSendEvent(); $reporter = $this->_createReporter(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar.tld' => 'Foo')) -> allowing($evt)->getMessage() -> returns($message) -> allowing($evt)->getFailedRecipients() -> returns(array()) -> one($reporter)->notify($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS) -> ignoring($message) -> ignoring($evt) ); $plugin = new Swift_Plugins_ReporterPlugin($reporter); $plugin->sendPerformed($evt); } public function testReportingFailedTo() { $message = $this->_createMessage(); $evt = $this->_createSendEvent(); $reporter = $this->_createReporter(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array( 'foo@bar.tld' => 'Foo', 'zip@button' => 'Zip' )) -> allowing($evt)->getMessage() -> returns($message) -> allowing($evt)->getFailedRecipients() -> returns(array('zip@button')) -> one($reporter)->notify($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS) -> one($reporter)->notify($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL) -> ignoring($message) -> ignoring($evt) ); $plugin = new Swift_Plugins_ReporterPlugin($reporter); $plugin->sendPerformed($evt); } public function testReportingFailedCc() { $message = $this->_createMessage(); $evt = $this->_createSendEvent(); $reporter = $this->_createReporter(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array( 'foo@bar.tld' => 'Foo' )) -> allowing($message)->getCc() -> returns(array( 'zip@button' => 'Zip', 'test@test.com' => 'Test' )) -> allowing($evt)->getMessage() -> returns($message) -> allowing($evt)->getFailedRecipients() -> returns(array('zip@button')) -> one($reporter)->notify($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS) -> one($reporter)->notify($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL) -> one($reporter)->notify($message, 'test@test.com', Swift_Plugins_Reporter::RESULT_PASS) -> ignoring($message) -> ignoring($evt) ); $plugin = new Swift_Plugins_ReporterPlugin($reporter); $plugin->sendPerformed($evt); } public function testReportingFailedBcc() { $message = $this->_createMessage(); $evt = $this->_createSendEvent(); $reporter = $this->_createReporter(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array( 'foo@bar.tld' => 'Foo' )) -> allowing($message)->getBcc() -> returns(array( 'zip@button' => 'Zip', 'test@test.com' => 'Test' )) -> allowing($evt)->getMessage() -> returns($message) -> allowing($evt)->getFailedRecipients() -> returns(array('zip@button')) -> one($reporter)->notify($message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS) -> one($reporter)->notify($message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL) -> one($reporter)->notify($message, 'test@test.com', Swift_Plugins_Reporter::RESULT_PASS) -> ignoring($message) -> ignoring($evt) ); $plugin = new Swift_Plugins_ReporterPlugin($reporter); $plugin->sendPerformed($evt); } // -- Creation Methods private function _createMessage() { return $this->_mock('Swift_Mime_Message'); } private function _createSendEvent() { return $this->_mock('Swift_Events_SendEvent'); } private function _createReporter() { return $this->_mock('Swift_Plugins_Reporter'); } } Swift-4.2.1/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php100644 0 0 4274 12000050367 22404 0ustar 0 0 _hitReporter = new Swift_Plugins_Reporters_HitReporter(); $this->_message = $this->_mock('Swift_Mime_Message'); } public function testReportingFail() { $this->_hitReporter->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_FAIL ); $this->assertEqual(array('foo@bar.tld'), $this->_hitReporter->getFailedRecipients() ); } public function testMultipleReports() { $this->_hitReporter->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_FAIL ); $this->_hitReporter->notify($this->_message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL ); $this->assertEqual(array('foo@bar.tld', 'zip@button'), $this->_hitReporter->getFailedRecipients() ); } public function testReportingPassIsIgnored() { $this->_hitReporter->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_FAIL ); $this->_hitReporter->notify($this->_message, 'zip@button', Swift_Plugins_Reporter::RESULT_PASS ); $this->assertEqual(array('foo@bar.tld'), $this->_hitReporter->getFailedRecipients() ); } public function testBufferCanBeCleared() { $this->_hitReporter->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_FAIL ); $this->_hitReporter->notify($this->_message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL ); $this->assertEqual(array('foo@bar.tld', 'zip@button'), $this->_hitReporter->getFailedRecipients() ); $this->_hitReporter->clear(); $this->assertEqual(array(), $this->_hitReporter->getFailedRecipients()); } } Swift-4.2.1/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php100644 0 0 3674 12000050367 22567 0ustar 0 0 _html = new Swift_Plugins_Reporters_HtmlReporter(); $this->_message = $this->_mock('Swift_Mime_Message'); } public function testReportingPass() { ob_start(); $this->_html->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS ); $html = ob_get_clean(); $this->assertPattern('~ok|pass~i', $html, '%s: Reporter should indicate pass'); $this->assertPattern('~foo@bar\.tld~', $html, '%s: Reporter should show address'); } public function testReportingFail() { ob_start(); $this->_html->notify($this->_message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL ); $html = ob_get_clean(); $this->assertPattern('~fail~i', $html, '%s: Reporter should indicate fail'); $this->assertPattern('~zip@button~', $html, '%s: Reporter should show address'); } public function testMultipleReports() { ob_start(); $this->_html->notify($this->_message, 'foo@bar.tld', Swift_Plugins_Reporter::RESULT_PASS ); $this->_html->notify($this->_message, 'zip@button', Swift_Plugins_Reporter::RESULT_FAIL ); $html = ob_get_clean(); $this->assertPattern('~ok|pass~i', $html, '%s: Reporter should indicate pass'); $this->assertPattern('~foo@bar\.tld~', $html, '%s: Reporter should show address'); $this->assertPattern('~fail~i', $html, '%s: Reporter should indicate fail'); $this->assertPattern('~zip@button~', $html, '%s: Reporter should show address'); } } Swift-4.2.1/tests/unit/Swift/Plugins/ThrottlerPluginTest.php100644 0 0 7345 12000050367 21320 0ustar 0 0 _createSleeper(); $timer = $this->_createTimer(); //10MB/min $plugin = new Swift_Plugins_ThrottlerPlugin( 10000000, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE, $sleeper, $timer ); $this->_checking(Expectations::create() -> one($timer)->getTimestamp() -> returns(0) -> one($timer)->getTimestamp() -> returns(1) //expected 0.6 -> one($timer)->getTimestamp() -> returns(1) //expected 1.2 (sleep 1) -> one($timer)->getTimestamp() -> returns(2) //expected 1.8 -> one($timer)->getTimestamp() -> returns(2) //expected 2.4 (sleep 1) -> ignoring($timer) -> exactly(2)->of($sleeper)->sleep(1) ); //10,000,000 bytes per minute //100,000 bytes per email // .: (10,000,000/100,000)/60 emails per second = 1.667 emais/sec $message = $this->_createMessageWithByteCount(100000); //100KB $evt = $this->_createSendEvent($message); for ($i = 0; $i < 5; ++$i) { $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } } public function testMessagesPerMinuteThrottling() { $sleeper = $this->_createSleeper(); $timer = $this->_createTimer(); //60/min $plugin = new Swift_Plugins_ThrottlerPlugin( 60, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE, $sleeper, $timer ); $this->_checking(Expectations::create() -> one($timer)->getTimestamp() -> returns(0) -> one($timer)->getTimestamp() -> returns(0) //expected 1 (sleep 1) -> one($timer)->getTimestamp() -> returns(2) //expected 2 -> one($timer)->getTimestamp() -> returns(2) //expected 3 (sleep 1) -> one($timer)->getTimestamp() -> returns(4) //expected 4 -> ignoring($timer) -> exactly(2)->of($sleeper)->sleep(1) ); //60 messages per minute //1 message per second $message = $this->_createMessageWithByteCount(10); $evt = $this->_createSendEvent($message); for ($i = 0; $i < 5; ++$i) { $plugin->beforeSendPerformed($evt); $plugin->sendPerformed($evt); } } // -- Creation Methods private function _createSleeper() { return $this->_mock('Swift_Plugins_Sleeper'); } private function _createTimer() { return $this->_mock('Swift_Plugins_Timer'); } private function _createMessageWithByteCount($bytes) { $this->_bytes = $bytes; $msg = $this->_mock('Swift_Mime_Message'); $this->_checking(Expectations::create() -> ignoring($msg)->toByteStream(any()) -> calls(array($this, '_write')) ); return $msg; } private function _createSendEvent($message) { $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> ignoring($evt)->getMessage() -> returns($message) ); return $evt; } private $_bytes = 0; public function _write($invocation) { $args = $invocation->getArguments(); $is = $args[0]; for ($i = 0; $i < $this->_bytes; ++$i) { $is->write('x'); } } } Swift-4.2.1/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php100644 0 0 11613 12000050367 24556 0ustar 0 0 _createFilter(array(0x61, 0x62), array(0x63, 0x64)); $this->assertEqual( array(0x59, 0x60, 0x63, 0x64, 0x65), $filter->filter(array(0x59, 0x60, 0x61, 0x62, 0x65)) ); } public function testShouldBufferReturnsTrueIfPartialMatchAtEndOfBuffer() { $filter = $this->_createFilter(array(0x61, 0x62), array(0x63, 0x64)); $this->assertTrue($filter->shouldBuffer(array(0x59, 0x60, 0x61)), '%s: Filter should buffer since 0x61 0x62 is the needle and the ending ' . '0x61 could be from 0x61 0x62' ); } public function testFilterCanMakeMultipleReplacements() { $filter = $this->_createFilter(array(array(0x61), array(0x62)), array(0x63)); $this->assertEqual( array(0x60, 0x63, 0x60, 0x63, 0x60), $filter->filter(array(0x60, 0x61, 0x60, 0x62, 0x60)) ); } public function testMultipleReplacementsCanBeDifferent() { $filter = $this->_createFilter(array(array(0x61), array(0x62)), array(array(0x63), array(0x64))); $this->assertEqual( array(0x60, 0x63, 0x60, 0x64, 0x60), $filter->filter(array(0x60, 0x61, 0x60, 0x62, 0x60)) ); } public function testShouldBufferReturnsFalseIfPartialMatchNotAtEndOfString() { $filter = $this->_createFilter(array(0x0D, 0x0A), array(0x0A)); $this->assertFalse($filter->shouldBuffer(array(0x61, 0x62, 0x0D, 0x0A, 0x63)), '%s: Filter should not buffer since x0Dx0A is the needle and is not at EOF' ); } public function testShouldBufferReturnsTrueIfAnyOfMultipleMatchesAtEndOfString() { $filter = $this->_createFilter(array(array(0x61, 0x62), array(0x63)), array(0x64)); $this->assertTrue($filter->shouldBuffer(array(0x59, 0x60, 0x61)), '%s: Filter should buffer since 0x61 0x62 is a needle and the ending ' . '0x61 could be from 0x61 0x62' ); } public function testConvertingAllLineEndingsToCRLFWhenInputIsLF() { $filter = $this->_createFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ); $this->assertEqual( array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63), $filter->filter(array(0x60, 0x0A, 0x61, 0x0A, 0x62, 0x0A, 0x63)) ); } public function testConvertingAllLineEndingsToCRLFWhenInputIsCR() { $filter = $this->_createFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ); $this->assertEqual( array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63), $filter->filter(array(0x60, 0x0D, 0x61, 0x0D, 0x62, 0x0D, 0x63)) ); } public function testConvertingAllLineEndingsToCRLFWhenInputIsCRLF() { $filter = $this->_createFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ); $this->assertEqual( array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63), $filter->filter(array(0x60, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x63)) ); } public function testConvertingAllLineEndingsToCRLFWhenInputIsLFCR() { $filter = $this->_createFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ); $this->assertEqual( array(0x60, 0x0D, 0x0A, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x0D, 0x0A, 0x63), $filter->filter(array(0x60, 0x0A, 0x0D, 0x61, 0x0A, 0x0D, 0x62, 0x0A, 0x0D, 0x63)) ); } public function testConvertingAllLineEndingsToCRLFWhenInputContainsLFLF() { //Lighthouse Bug #23 $filter = $this->_createFilter( array(array(0x0D, 0x0A), array(0x0D), array(0x0A)), array(array(0x0A), array(0x0A), array(0x0D, 0x0A)) ); $this->assertEqual( array(0x60, 0x0D, 0x0A, 0x0D, 0x0A, 0x61, 0x0D, 0x0A, 0x0D, 0x0A, 0x62, 0x0D, 0x0A, 0x0D, 0x0A, 0x63), $filter->filter(array(0x60, 0x0A, 0x0A, 0x61, 0x0A, 0x0A, 0x62, 0x0A, 0x0A, 0x63)) ); } // -- Creation methods private function _createFilter($search, $replace) { return new Swift_StreamFilters_ByteArrayReplacementFilter($search, $replace); } } Swift-4.2.1/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php100644 0 0 2404 12000050367 25430 0ustar 0 0 _createFactory(); $this->assertIsA($factory->createFilter('a', 'b'), 'Swift_StreamFilters_StringReplacementFilter' ); } public function testSameInstancesAreCached() { $factory = $this->_createFactory(); $filter1 = $factory->createFilter('a', 'b'); $filter2 = $factory->createFilter('a', 'b'); $this->assertSame($filter1, $filter2, '%s: Instances should be cached'); } public function testDifferingInstancesAreNotCached() { $factory = $this->_createFactory(); $filter1 = $factory->createFilter('a', 'b'); $filter2 = $factory->createFilter('a', 'c'); $this->assertNotEqual($filter1, $filter2, '%s: Differing instances should not be cached' ); } // -- Creation methods private function _createFactory() { return new Swift_StreamFilters_StringReplacementFilterFactory(); } } Swift-4.2.1/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php100644 0 0 3752 12000050367 24107 0ustar 0 0 _createFilter('foo', 'bar'); $this->assertEqual('XbarYbarZ', $filter->filter('XfooYfooZ')); } public function testShouldBufferReturnsTrueIfPartialMatchAtEndOfBuffer() { $filter = $this->_createFilter('foo', 'bar'); $this->assertTrue($filter->shouldBuffer('XfooYf'), '%s: Filter should buffer since "foo" is the needle and the ending ' . '"f" could be from "foo"' ); } public function testFilterCanMakeMultipleReplacements() { $filter = $this->_createFilter(array('a', 'b'), 'foo'); $this->assertEqual('XfooYfooZ', $filter->filter('XaYbZ')); } public function testMultipleReplacementsCanBeDifferent() { $filter = $this->_createFilter(array('a', 'b'), array('foo', 'zip')); $this->assertEqual('XfooYzipZ', $filter->filter('XaYbZ')); } public function testShouldBufferReturnsFalseIfPartialMatchNotAtEndOfString() { $filter = $this->_createFilter("\r\n", "\n"); $this->assertFalse($filter->shouldBuffer("foo\r\nbar"), '%s: Filter should not buffer since x0Dx0A is the needle and is not at EOF' ); } public function testShouldBufferReturnsTrueIfAnyOfMultipleMatchesAtEndOfString() { $filter = $this->_createFilter(array('foo', 'zip'), 'bar'); $this->assertTrue($filter->shouldBuffer('XfooYzi'), '%s: Filter should buffer since "zip" is a needle and the ending ' . '"zi" could be from "zip"' ); } // -- Creation methods private function _createFilter($search, $replace) { return new Swift_StreamFilters_StringReplacementFilter($search, $replace); } } Swift-4.2.1/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php100644 0 0 40154 12000050367 23546 0ustar 0 0 _getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $listener = $this->_mock('Swift_Events_EventListener'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> one($dispatcher)->bindEventListener($listener) ); $smtp->registerPlugin($listener); } public function testSendingDispatchesBeforeSendEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $message = $this->_createMessage(); $smtp = $this->_getTransport($buf, $dispatcher); $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array('mark@swiftmailer.org'=>'Mark')) -> ignoring($message) -> one($dispatcher)->createSendEvent(optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeSendPerformed') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(1, $smtp->send($message)); } public function testSendingDispatchesSendEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $message = $this->_createMessage(); $smtp = $this->_getTransport($buf, $dispatcher); $evt = $this->_mock('Swift_Events_SendEvent'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array('mark@swiftmailer.org'=>'Mark')) -> ignoring($message) -> one($dispatcher)->createSendEvent(optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'sendPerformed') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(1, $smtp->send($message)); } public function testSendEventCapturesFailures() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_SendEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array('mark@swiftmailer.org'=>'Mark')) -> ignoring($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("500 Not now\r\n") -> allowing($dispatcher)->createSendEvent($smtp, optional()) -> returns($evt) -> one($evt)->setFailedRecipients(array('mark@swiftmailer.org')) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(0, $smtp->send($message)); } public function testSendEventHasResultFailedIfAllFailures() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_SendEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array('mark@swiftmailer.org'=>'Mark')) -> ignoring($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("500 Not now\r\n") -> allowing($dispatcher)->createSendEvent($smtp, optional()) -> returns($evt) -> one($evt)->setResult(Swift_Events_SendEvent::RESULT_FAILED) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(0, $smtp->send($message)); } public function testSendEventHasResultTentativeIfSomeFailures() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_SendEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array( 'mark@swiftmailer.org'=>'Mark', 'chris@site.tld'=>'Chris' )) -> ignoring($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("500 Not now\r\n") -> allowing($dispatcher)->createSendEvent($smtp, optional()) -> returns($evt) -> one($evt)->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(1, $smtp->send($message)); } public function testSendEventHasResultSuccessIfNoFailures() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_SendEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array( 'mark@swiftmailer.org'=>'Mark', 'chris@site.tld'=>'Chris' )) -> ignoring($message) -> allowing($dispatcher)->createSendEvent($smtp, optional()) -> returns($evt) -> one($evt)->setResult(Swift_Events_SendEvent::RESULT_SUCCESS) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(2, $smtp->send($message)); } public function testCancellingEventBubbleBeforeSendStopsEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_SendEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('chris@swiftmailer.org'=>null)) -> allowing($message)->getTo() -> returns(array('mark@swiftmailer.org'=>'Mark')) -> ignoring($message) -> allowing($dispatcher)->createSendEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeSendPerformed') -> ignoring($dispatcher) -> atLeast(1)->of($evt)->bubbleCancelled() -> returns(true) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(0, $smtp->send($message)); } public function testStartingTransportDispatchesTransportChangeEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'transportStarted') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); } public function testStartingTransportDispatchesBeforeTransportChangeEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeTransportStarted') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); } public function testCancellingBubbleBeforeTransportStartStopsEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeTransportStarted') -> allowing($evt)->bubbleCancelled() -> returns(true) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $this->assertFalse($smtp->isStarted(), '%s: Transport should not be started since event bubble was cancelled' ); } public function testStoppingTransportDispatchesTransportChangeEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'transportStopped') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->stop(); } public function testStoppingTransportDispatchesBeforeTransportChangeEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeTransportStopped') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->stop(); } public function testCancellingBubbleBeforeTransportStoppedStopsEvent() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportChangeEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $seq = $this->_sequence('stopping transport'); $this->_checking(Expectations::create() -> allowing($dispatcher)->createTransportChangeEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'beforeTransportStopped') -> inSequence($seq) -> allowing($evt)->bubbleCancelled() -> inSequence($seq) -> returns(true) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->stop(); $this->assertTrue($smtp->isStarted(), '%s: Transport should not be stopped since event bubble was cancelled' ); } public function testResponseEventsAreGenerated() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_ResponseEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createResponseEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'responseReceived') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); } public function testCommandEventsAreGenerated() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_CommandEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> allowing($dispatcher)->createCommandEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'commandSent') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); } public function testExceptionsCauseExceptionEvents() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportExceptionEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> atLeast(1)->of($buf)->readLine(any()) -> returns("503 I'm sleepy, go away!\r\n") -> allowing($dispatcher)->createTransportExceptionEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'exceptionThrown') -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); try { $smtp->start(); $this->fail('TransportException should be thrown on invalid response'); } catch (Swift_TransportException $e) { } } public function testExceptionBubblesCanBeCancelled() { $buf = $this->_getBuffer(); $dispatcher = $this->_createEventDispatcher(false); $evt = $this->_mock('Swift_Events_TransportExceptionEvent'); $smtp = $this->_getTransport($buf, $dispatcher); $this->_checking(Expectations::create() -> atLeast(1)->of($buf)->readLine(any()) -> returns("503 I'm sleepy, go away!\r\n") -> allowing($dispatcher)->createTransportExceptionEvent($smtp, optional()) -> returns($evt) -> one($dispatcher)->dispatchEvent($evt, 'exceptionThrown') -> atLeast(1)->of($evt)->bubbleCancelled() -> returns(true) -> ignoring($dispatcher) -> ignoring($evt) ); $this->_finishBuffer($buf); $smtp->start(); } // -- Creation Methods protected function _createEventDispatcher($stub = true) { return $stub ? $this->_stub('Swift_Events_EventDispatcher') : $this->_mock('Swift_Events_EventDispatcher') ; } } Swift-4.2.1/tests/unit/Swift/Transport/AbstractSmtpTest.php100644 0 0 112466 12000050367 21175 0ustar 0 0 _getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") ); $this->_finishBuffer($buf); try { $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started'); $smtp->start(); $this->assertTrue($smtp->isStarted(), '%s: start() should have started connection'); } catch (Exception $e) { $this->fail('220 is a valid SMTP greeting and should be accepted'); } } public function testBadGreetingCausesException() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("554 I'm busy\r\n") ); $this->_finishBuffer($buf); try { $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started'); $smtp->start(); $this->fail('554 greeting indicates an error and should cause an exception'); } catch (Exception $e) { $this->assertFalse($smtp->isStarted(), '%s: start() should have failed'); } } public function testStartSendsHeloToInitiate() { /* -- RFC 2821, 3.2. 3.2 Client Initiation Once the server has sent the welcoming message and the client has received it, the client normally sends the EHLO command to the server, indicating the client's identity. In addition to opening the session, use of EHLO indicates that the client is able to process service extensions and requests that the server provide a list of the extensions it supports. Older SMTP systems which are unable to support service extensions and contemporary clients which do not require service extensions in the mail session being initiated, MAY use HELO instead of EHLO. Servers MUST NOT return the extended EHLO-style response to a HELO command. For a particular connection attempt, if the server returns a "command not recognized" response to EHLO, the client SHOULD be able to fall back and send HELO. In the EHLO command the host sending the command identifies itself; the command may be interpreted as saying "Hello, I am " (and, in the case of EHLO, "and I support service extension requests"). -- RFC 2281, 4.1.1.1. ehlo = "EHLO" SP Domain CRLF helo = "HELO" SP Domain CRLF -- RFC 2821, 4.3.2. EHLO or HELO S: 250 E: 504, 550 */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^HELO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('250 ServerName' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); } catch (Exception $e) { $this->fail('Starting SMTP should send HELO and accept 250 response'); } } public function testInvalidHeloResponseCausesException() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^HELO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('504 WTF' . "\r\n") ); $this->_finishBuffer($buf); try { $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started'); $smtp->start(); $this->fail('Non 250 HELO response should raise Exception'); } catch (Exception $e) { $this->assertFalse($smtp->isStarted(), '%s: SMTP start() should have failed'); } } public function testDomainNameIsPlacedInHelo() { /* -- RFC 2821, 4.1.4. The SMTP client MUST, if possible, ensure that the domain parameter to the EHLO command is a valid principal host name (not a CNAME or MX name) for its host. If this is not possible (e.g., when the client's address is dynamically assigned and the client does not have an obvious name), an address literal SHOULD be substituted for the domain name and supplemental information provided that will assist in identifying the client. */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write("HELO mydomain.com\r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('250 ServerName' . "\r\n") ); $this->_finishBuffer($buf); $smtp->setLocalDomain('mydomain.com'); $smtp->start(); } public function testSuccessfulMailCommand() { /* -- RFC 2821, 3.3. There are three steps to SMTP mail transactions. The transaction starts with a MAIL command which gives the sender identification. ..... The first step in the procedure is the MAIL command. MAIL FROM: [SP ] -- RFC 2821, 4.1.1.2. Syntax: "MAIL FROM:" ("<>" / Reverse-Path) [SP Mail-parameters] CRLF -- RFC 2821, 4.1.2. Reverse-path = Path Forward-path = Path Path = "<" [ A-d-l ":" ] Mailbox ">" A-d-l = At-domain *( "," A-d-l ) ; Note that this form, the so-called "source route", ; MUST BE accepted, SHOULD NOT be generated, and SHOULD be ; ignored. At-domain = "@" domain -- RFC 2821, 4.3.2. MAIL S: 250 E: 552, 451, 452, 550, 553, 503 */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); } catch (Exception $e) { $this->fail('MAIL FROM should accept a 250 response'); } } public function testInvalidResponseCodeFromMailCausesException() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('553 Bad' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); $this->fail('MAIL FROM should accept a 250 response'); } catch (Exception $e) { } } public function testSenderIsPreferredOverFrom() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getSender() -> returns(array('another@domain.com'=>'Someone')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testReturnPathIsPreferredOverSender() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getSender() -> returns(array('another@domain.com'=>'Someone')) -> allowing($message)->getReturnPath() -> returns('more@domain.com') -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testSuccessfulRcptCommandWith250Response() { /* -- RFC 2821, 3.3. The second step in the procedure is the RCPT command. RCPT TO: [ SP ] The first or only argument to this command includes a forward-path (normally a mailbox and domain, always surrounded by "<" and ">" brackets) identifying one recipient. If accepted, the SMTP server returns a 250 OK reply and stores the forward-path. If the recipient is known not to be a deliverable address, the SMTP server returns a 550 reply, typically with a string such as "no such user - " and the mailbox name (other circumstances and reply codes are possible). This step of the procedure can be repeated any number of times. -- RFC 2821, 4.1.1.3. This command is used to identify an individual recipient of the mail data; multiple recipients are specified by multiple use of this command. The argument field contains a forward-path and may contain optional parameters. The forward-path normally consists of the required destination mailbox. Sending systems SHOULD not generate the optional list of hosts known as a source route. ....... "RCPT TO:" ("" / "" / Forward-Path) [SP Rcpt-parameters] CRLF -- RFC 2821, 4.2.2. 250 Requested mail action okay, completed 251 User not local; will forward to (See section 3.4) 252 Cannot VRFY user, but will accept message and attempt delivery -- RFC 2821, 4.3.2. RCPT S: 250, 251 (but see section 3.4 for discussion of 251 and 551) E: 550, 551, 552, 553, 450, 451, 452, 503, 550 */ //We'll treat 252 as accepted since it isn't really a failure $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $s = $this->_sequence('SMTP-envelope'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); } catch (Exception $e) { $this->fail('RCPT TO should accept a 250 response'); } } public function testMailFromCommandIsOnlySentOncePerMessage() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $s = $this->_sequence('SMTP-envelope'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") -> never($buf)->write("MAIL FROM: \r\n") ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testMultipleRecipientsSendsMultipleRcpt() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array( 'foo@bar' => null, 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("RCPT TO: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(3) -> one($buf)->readLine(3) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testCcRecipientsSendsMultipleRcpt() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getCc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("RCPT TO: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(3) -> one($buf)->readLine(3) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testSendReturnsNumberOfSuccessfulRecipients() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getCc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("RCPT TO: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('250 OK' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns('501 Nobody here' . "\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(3) -> one($buf)->readLine(3) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(2, $smtp->send($message), '%s: 1 of 3 recipients failed so 2 should be returned' ); } public function testRsetIsSentIfNoSuccessfulRecipients() { /* --RFC 2821, 4.1.1.5. This command specifies that the current mail transaction will be aborted. Any stored sender, recipients, and mail data MUST be discarded, and all buffers and state tables cleared. The receiver MUST send a "250 OK" reply to a RSET command with no arguments. A reset command may be issued by the client at any time. -- RFC 2821, 4.3.2. RSET S: 250 */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message) -> one($buf)->write("RCPT TO: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('503 Bad' . "\r\n") -> one($buf)->write("RSET\r\n") -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(0, $smtp->send($message), '%s: 1 of 1 recipients failed so 0 should be returned' ); } public function testSuccessfulDataCommand() { /* -- RFC 2821, 3.3. The third step in the procedure is the DATA command (or some alternative specified in a service extension). DATA If accepted, the SMTP server returns a 354 Intermediate reply and considers all succeeding lines up to but not including the end of mail data indicator to be the message text. -- RFC 2821, 4.1.1.4. The receiver normally sends a 354 response to DATA, and then treats the lines (strings ending in sequences, as described in section 2.3.7) following the command as mail data from the sender. This command causes the mail data to be appended to the mail data buffer. The mail data may contain any of the 128 ASCII character codes, although experience has indicated that use of control characters other than SP, HT, CR, and LF may cause problems and SHOULD be avoided when possible. -- RFC 2821, 4.3.2. DATA I: 354 -> data -> S: 250 E: 552, 554, 451, 452 E: 451, 554, 503 */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message) -> one($buf)->write("DATA\r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('354 Go ahead' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); } catch (Exception $e) { $this->fail('354 is the expected response to DATA'); } } public function testBadDataResponseCausesException() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message) -> one($buf)->write("DATA\r\n") -> returns(1) -> one($buf)->readLine(1) -> returns('451 Bad' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); $this->fail('354 is the expected response to DATA (not observed)'); } catch (Exception $e) { } } public function testMessageIsStreamedToBufferForData() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $s = $this->_sequence('DATA Streaming'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> one($buf)->write("DATA\r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> returns('354 OK' . "\r\n") -> one($message)->toByteStream($buf) -> inSequence($s) -> one($buf)->write("\r\n.\r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> returns('250 OK' . "\r\n") -> allowing($message) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testBadResponseAfterDataTransmissionCausesException() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $s = $this->_sequence('DATA Streaming'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> one($buf)->write("DATA\r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> returns('354 OK' . "\r\n") -> one($message)->toByteStream($buf) -> inSequence($s) -> one($buf)->write("\r\n.\r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> returns('554 Error' . "\r\n") -> allowing($message) ); $this->_finishBuffer($buf); try { $smtp->start(); $smtp->send($message); $this->fail('250 is the expected response after a DATA transmission (not observed)'); } catch (Exception $e) { } } public function testBccRecipientsAreRemovedFromHeaders() { /* -- RFC 2821, 7.2. Addresses that do not appear in the message headers may appear in the RCPT commands to an SMTP server for a number of reasons. The two most common involve the use of a mailing address as a "list exploder" (a single address that resolves into multiple addresses) and the appearance of "blind copies". Especially when more than one RCPT command is present, and in order to avoid defeating some of the purpose of these mechanisms, SMTP clients and servers SHOULD NOT copy the full set of RCPT command arguments into the headers, either as part of trace headers or as informational or private-extension headers. Since this rule is often violated in practice, and cannot be enforced, sending SMTP systems that are aware of "bcc" use MAY find it helpful to send each blind copy as a separate message transaction containing only a single RCPT command. */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getBcc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> atLeast(1)->of($message)->setBcc(array()) -> allowing($message) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } public function testEachBccRecipientIsSentASeparateMessage() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getBcc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> atLeast(1)->of($message)->setBcc(array()) -> one($message)->setBcc(array('zip@button' => 'Zip Button')) -> one($message)->setBcc(array('test@domain' => 'Test user')) -> atLeast(1)->of($message)->setBcc(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("250 OK\r\n") -> one($buf)->write("DATA\r\n") -> returns(3) -> one($buf)->readLine(3) -> returns("354 OK\r\n") -> one($buf)->write("\r\n.\r\n") -> returns(4) -> one($buf)->readLine(4) -> returns("250 OK\r\n") -> one($buf)->write("MAIL FROM: \r\n") -> returns(5) -> one($buf)->readLine(5) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(6) -> one($buf)->readLine(6) -> returns("250 OK\r\n") -> one($buf)->write("DATA\r\n") -> returns(7) -> one($buf)->readLine(7) -> returns("354 OK\r\n") -> one($buf)->write("\r\n.\r\n") -> returns(8) -> one($buf)->readLine(8) -> returns("250 OK\r\n") -> one($buf)->write("MAIL FROM: \r\n") -> returns(9) -> one($buf)->readLine(9) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(10) -> one($buf)->readLine(10) -> returns("250 OK\r\n") -> one($buf)->write("DATA\r\n") -> returns(11) -> one($buf)->readLine(11) -> returns("354 OK\r\n") -> one($buf)->write("\r\n.\r\n") -> returns(12) -> one($buf)->readLine(12) -> returns("250 OK\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(3, $smtp->send($message)); } public function testMessageStateIsRestoredOnFailure() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getBcc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> one($message)->setBcc(array()) -> one($message)->setBcc(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("250 OK\r\n") -> one($buf)->write("DATA\r\n") -> returns(3) -> one($buf)->readLine(3) -> returns("451 No\r\n") ); $this->_finishBuffer($buf); $smtp->start(); try { $smtp->send($message); $this->fail('A bad response was given so exception is expected'); } catch (Exception $e) { } } public function testStopSendsQuitCommand() { /* -- RFC 2821, 4.1.1.10. This command specifies that the receiver MUST send an OK reply, and then close the transmission channel. The receiver MUST NOT intentionally close the transmission channel until it receives and replies to a QUIT command (even if there was an error). The sender MUST NOT intentionally close the transmission channel until it sends a QUIT command and SHOULD wait until it receives the reply (even if there was an error response to a previous command). If the connection is closed prematurely due to violations of the above or system or network failure, the server MUST cancel any pending transaction, but not undo any previously completed transaction, and generally MUST act as if the command or transaction in progress had received a temporary error (i.e., a 4yz response). The QUIT command may be issued at any time. Syntax: "QUIT" CRLF */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($buf)->initialize() -> one($buf)->write("QUIT\r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("221 Bye\r\n") -> one($buf)->terminate() ); $this->_finishBuffer($buf); $this->assertFalse($smtp->isStarted()); $smtp->start(); $this->assertTrue($smtp->isStarted()); $smtp->stop(); $this->assertFalse($smtp->isStarted()); } public function testBufferCanBeFetched() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ref = $smtp->getBuffer(); $this->assertReference($buf, $ref); } public function testBufferCanBeWrittenToUsingExecuteCommand() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($buf)->write("FOO\r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> ignoring($buf) ); $res = $smtp->executeCommand("FOO\r\n"); $this->assertEqual("250 OK\r\n", $res); } public function testResponseCodesAreValidated() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> one($buf)->write("FOO\r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("551 Not ok\r\n") -> ignoring($buf) ); try { $smtp->executeCommand("FOO\r\n", array(250, 251)); $this->fail('A 250 or 251 response was needed but 551 was returned.'); } catch (Exception $e) { } } public function testFailedRecipientsCanBeCollectedByReference() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar' => null)) -> allowing($message)->getBcc() -> returns(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> atLeast(1)->of($message)->setBcc(array()) -> one($message)->setBcc(array('zip@button' => 'Zip Button')) -> one($message)->setBcc(array('test@domain' => 'Test user')) -> atLeast(1)->of($message)->setBcc(array( 'zip@button' => 'Zip Button', 'test@domain' => 'Test user' )) -> allowing($message) -> one($buf)->write("MAIL FROM: \r\n") -> returns(1) -> one($buf)->readLine(1) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(2) -> one($buf)->readLine(2) -> returns("250 OK\r\n") -> one($buf)->write("DATA\r\n") -> returns(3) -> one($buf)->readLine(3) -> returns("354 OK\r\n") -> one($buf)->write("\r\n.\r\n") -> returns(4) -> one($buf)->readLine(4) -> returns("250 OK\r\n") -> one($buf)->write("MAIL FROM: \r\n") -> returns(5) -> one($buf)->readLine(5) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(6) -> one($buf)->readLine(6) -> returns("500 Bad\r\n") -> one($buf)->write("RSET\r\n") -> returns(7) -> one($buf)->readLine(7) -> returns("250 OK\r\n") -> one($buf)->write("MAIL FROM: \r\n") -> returns(8) -> one($buf)->readLine(8) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> returns(9) -> one($buf)->readLine(9) -> returns("500 Bad\r\n") -> one($buf)->write("RSET\r\n") -> returns(10) -> one($buf)->readLine(10) -> returns("250 OK\r\n") ); $this->_finishBuffer($buf); $smtp->start(); $this->assertEqual(1, $smtp->send($message, $failures)); $this->assertEqual(array('zip@button', 'test@domain'), $failures, '%s: Failures should be caught in an array' ); } public function testSendingRegeneratesMessageId() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain.com'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> one($message)->generateId() -> allowing($message) ); $this->_finishBuffer($buf); $smtp->start(); $smtp->send($message); } // -- Protected methods protected function _getBuffer() { return $this->_mock('Swift_Transport_IoBuffer'); } protected function _createMessage() { return $this->_mock('Swift_Mime_Message'); } protected function _finishBuffer($buf) { $this->_checking(Expectations::create() -> ignoring($buf)->readLine(0) -> returns('220 server.com foo' . "\r\n") -> ignoring($buf)->write(pattern('~^(EH|HE)LO .*?\r\n$~D')) -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns('250 ServerName' . "\r\n") -> ignoring($buf)->write(pattern('~^MAIL FROM: <.*?>\r\n$~D')) -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns('250 OK' . "\r\n") -> ignoring($buf)->write(pattern('~^RCPT TO: <.*?>\r\n$~D')) -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns('250 OK' . "\r\n") -> ignoring($buf)->write("DATA\r\n") -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns('354 OK' . "\r\n") -> ignoring($buf)->write("\r\n.\r\n") -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns('250 OK' . "\r\n") -> ignoring($buf)->write("RSET\r\n") -> returns($x = uniqid()) -> ignoring($buf)->readLine($x) -> returns("250 OK\r\n") -> ignoring($buf) -> returns(false) ); } } Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php100644 0 0 4411 12000050367 24470 0ustar 0 0 _agent = $this->_mock('Swift_Transport_SmtpAgent'); } public function testKeywordIsCramMd5() { /* -- RFC 2195, 2. The authentication type associated with CRAM is "CRAM-MD5". */ $cram = $this->_getAuthenticator(); $this->assertEqual('CRAM-MD5', $cram->getAuthKeyword()); } public function testSuccessfulAuthentication() { $cram = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand("AUTH CRAM-MD5\r\n", array(334)) -> returns('334 ' . base64_encode('') . "\r\n") // The use of any() is controversial, but here to avoid crazy test logic -> one($this->_agent)->executeCommand(any(), array(235)) ); $this->assertTrue($cram->authenticate($this->_agent, 'jack', 'pass'), '%s: The buffer accepted all commands authentication should succeed' ); } public function testAuthenticationFailureSendRsetAndReturnFalse() { $cram = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand("AUTH CRAM-MD5\r\n", array(334)) -> returns('334 ' . base64_encode('') . "\r\n") // The use of any() is controversial, but here to avoid crazy test logic -> one($this->_agent)->executeCommand(any(), array(235)) -> throws(new Swift_TransportException("")) -> one($this->_agent)->executeCommand("RSET\r\n", array(250)) ); $this->assertFalse($cram->authenticate($this->_agent, 'jack', 'pass'), '%s: Authentication fails, so RSET should be sent' ); } // -- Private helpers private function _getAuthenticator() { return new Swift_Transport_Esmtp_Auth_CramMd5Authenticator(); } } Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php100644 0 0 4115 12000050367 24311 0ustar 0 0 _agent = $this->_mock('Swift_Transport_SmtpAgent'); } public function testKeywordIsLogin() { $login = $this->_getAuthenticator(); $this->assertEqual('LOGIN', $login->getAuthKeyword()); } public function testSuccessfulAuthentication() { $login = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand("AUTH LOGIN\r\n", array(334)) -> one($this->_agent)->executeCommand(base64_encode('jack') . "\r\n", array(334)) -> one($this->_agent)->executeCommand(base64_encode('pass') . "\r\n", array(235)) ); $this->assertTrue($login->authenticate($this->_agent, 'jack', 'pass'), '%s: The buffer accepted all commands authentication should succeed' ); } public function testAuthenticationFailureSendRsetAndReturnFalse() { $login = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand("AUTH LOGIN\r\n", array(334)) -> one($this->_agent)->executeCommand(base64_encode('jack') . "\r\n", array(334)) -> one($this->_agent)->executeCommand(base64_encode('pass') . "\r\n", array(235)) -> throws(new Swift_TransportException("")) -> one($this->_agent)->executeCommand("RSET\r\n", array(250)) ); $this->assertFalse($login->authenticate($this->_agent, 'jack', 'pass'), '%s: Authentication fails, so RSET should be sent' ); } // -- Private helpers private function _getAuthenticator() { return new Swift_Transport_Esmtp_Auth_LoginAuthenticator(); } } Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php100644 0 0 4476 12000050367 24316 0ustar 0 0 _agent = $this->_mock('Swift_Transport_SmtpAgent'); } public function testKeywordIsPlain() { /* -- RFC 4616, 1. The name associated with this mechanism is "PLAIN". */ $login = $this->_getAuthenticator(); $this->assertEqual('PLAIN', $login->getAuthKeyword()); } public function testSuccessfulAuthentication() { /* -- RFC 4616, 2. The client presents the authorization identity (identity to act as), followed by a NUL (U+0000) character, followed by the authentication identity (identity whose password will be used), followed by a NUL (U+0000) character, followed by the clear-text password. */ $plain = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand('AUTH PLAIN ' . base64_encode( 'jack' . chr(0) . 'jack' . chr(0) . 'pass' ) . "\r\n", array(235)) ); $this->assertTrue($plain->authenticate($this->_agent, 'jack', 'pass'), '%s: The buffer accepted all commands authentication should succeed' ); } public function testAuthenticationFailureSendRsetAndReturnFalse() { $plain = $this->_getAuthenticator(); $this->_checking(Expectations::create() -> one($this->_agent)->executeCommand('AUTH PLAIN ' . base64_encode( 'jack' . chr(0) . 'jack' . chr(0) . 'pass' ) . "\r\n", array(235)) -> throws(new Swift_TransportException("")) -> one($this->_agent)->executeCommand("RSET\r\n", array(250)) ); $this->assertFalse($plain->authenticate($this->_agent, 'jack', 'pass'), '%s: Authentication fails, so RSET should be sent' ); } // -- Private helpers private function _getAuthenticator() { return new Swift_Transport_Esmtp_Auth_PlainAuthenticator(); } } Swift-4.2.1/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php100644 0 0 12353 12000050367 22027 0ustar 0 0 _agent = $this->_mock('Swift_Transport_SmtpAgent'); } public function testKeywordIsAuth() { $auth = $this->_createHandler(array()); $this->assertEqual('AUTH', $auth->getHandledKeyword()); } public function testUsernameCanBeSetAndFetched() { $auth = $this->_createHandler(array()); $auth->setUsername('jack'); $this->assertEqual('jack', $auth->getUsername()); } public function testPasswordCanBeSetAndFetched() { $auth = $this->_createHandler(array()); $auth->setPassword('pass'); $this->assertEqual('pass', $auth->getPassword()); } public function testAuthModeCanBeSetAndFetched() { $auth = $this->_createHandler(array()); $auth->setAuthMode('PLAIN'); $this->assertEqual('PLAIN', $auth->getAuthMode()); } public function testMixinMethods() { $auth = $this->_createHandler(array()); $mixins = $auth->exposeMixinMethods(); $this->assertTrue(in_array('getUsername', $mixins), '%s: getUsername() should be accessible via mixin' ); $this->assertTrue(in_array('setUsername', $mixins), '%s: setUsername() should be accessible via mixin' ); $this->assertTrue(in_array('getPassword', $mixins), '%s: getPassword() should be accessible via mixin' ); $this->assertTrue(in_array('setPassword', $mixins), '%s: setPassword() should be accessible via mixin' ); $this->assertTrue(in_array('setAuthMode', $mixins), '%s: setAuthMode() should be accessible via mixin' ); $this->assertTrue(in_array('getAuthMode', $mixins), '%s: getAuthMode() should be accessible via mixin' ); } public function testAuthenticatorsAreCalledAccordingToParamsAfterEhlo() { $a1 = $this->_createMockAuthenticator('PLAIN'); $a2 = $this->_createMockAuthenticator('LOGIN'); $this->_checking(Expectations::create() -> never($a1)->authenticate($this->_agent, 'jack', 'pass') -> one($a2)->authenticate($this->_agent, 'jack', 'pass') -> returns(true) ); $auth = $this->_createHandler(array($a1, $a2)); $auth->setUsername('jack'); $auth->setPassword('pass'); $auth->setKeywordParams(array('CRAM-MD5', 'LOGIN')); $auth->afterEhlo($this->_agent); } public function testAuthenticatorsAreNotUsedIfNoUsernameSet() { $a1 = $this->_createMockAuthenticator('PLAIN'); $a2 = $this->_createMockAuthenticator('LOGIN'); $this->_checking(Expectations::create() -> never($a1)->authenticate($this->_agent, 'jack', 'pass') -> never($a2)->authenticate($this->_agent, 'jack', 'pass') -> returns(true) ); $auth = $this->_createHandler(array($a1, $a2)); $auth->setKeywordParams(array('CRAM-MD5', 'LOGIN')); $auth->afterEhlo($this->_agent); } public function testSeveralAuthenticatorsAreTriedIfNeeded() { $a1 = $this->_createMockAuthenticator('PLAIN'); $a2 = $this->_createMockAuthenticator('LOGIN'); $this->_checking(Expectations::create() -> one($a1)->authenticate($this->_agent, 'jack', 'pass') -> returns(false) -> one($a2)->authenticate($this->_agent, 'jack', 'pass') -> returns(true) ); $auth = $this->_createHandler(array($a1, $a2)); $auth->setUsername('jack'); $auth->setPassword('pass'); $auth->setKeywordParams(array('PLAIN', 'LOGIN')); $auth->afterEhlo($this->_agent); } public function testFirstAuthenticatorToPassBreaksChain() { $a1 = $this->_createMockAuthenticator('PLAIN'); $a2 = $this->_createMockAuthenticator('LOGIN'); $a3 = $this->_createMockAuthenticator('CRAM-MD5'); $this->_checking(Expectations::create() -> one($a1)->authenticate($this->_agent, 'jack', 'pass') -> returns(false) -> one($a2)->authenticate($this->_agent, 'jack', 'pass') -> returns(true) -> never($a3)->authenticate($this->_agent, 'jack', 'pass') ); $auth = $this->_createHandler(array($a1, $a2)); $auth->setUsername('jack'); $auth->setPassword('pass'); $auth->setKeywordParams(array('PLAIN', 'LOGIN', 'CRAM-MD5')); $auth->afterEhlo($this->_agent); } // -- Private helpers private function _createHandler($authenticators) { return new Swift_Transport_Esmtp_AuthHandler($authenticators); } private function _createMockAuthenticator($type) { $authenticator = $this->_mock('Swift_Transport_Esmtp_Authenticator'); $this->_checking(Expectations::create() -> ignoring($authenticator)->getAuthKeyword() -> returns($type) ); return $authenticator; } } Swift-4.2.1/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php100644 0 0 36161 12000050367 25121 0ustar 0 0 _getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $this->_checking(Expectations::create() -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> allowing($ext1)->getPriorityOver('STARTTLS') -> returns(0) -> allowing($ext2)->getHandledKeyword() -> returns('STARTTLS') -> allowing($ext2)->getPriorityOver('AUTH') -> returns(-1) -> ignoring($ext1) -> ignoring($ext2) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2)); $this->assertEqual(array($ext2, $ext1), $smtp->getExtensionHandlers()); } public function testHandlersAreNotifiedOfParams() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->setKeywordParams(array('PLAIN', 'LOGIN')) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> allowing($ext2)->setKeywordParams(array('123456')) -> ignoring($ext1) -> ignoring($ext2) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2)); $smtp->start(); } public function testSupportedExtensionHandlersAreRunAfterEhlo() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext3 = $this->_mock('Swift_Transport_EsmtpHandler'); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->afterEhlo($smtp) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> allowing($ext2)->afterEhlo($smtp) -> allowing($ext3)->getHandledKeyword() -> returns('STARTTLS') -> never($ext3)->afterEhlo(any()) -> ignoring($ext1) -> ignoring($ext2) -> ignoring($ext3) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3)); $smtp->start(); } public function testExtensionsCanModifyMailFromParams() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext3 = $this->_mock('Swift_Transport_EsmtpHandler'); $message = $this->_createMessage(); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> ignoring($message) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> one($buf)->write("MAIL FROM: FOO ZIP\r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: \r\n") -> inSequence($s) -> returns(3) -> one($buf)->readLine(3) -> inSequence($s) -> returns("250 OK\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->getMailParams() -> returns('FOO') -> allowing($ext1)->getPriorityOver('AUTH') -> returns(-1) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> one($ext2)->getMailParams() -> returns('ZIP') -> allowing($ext2)->getPriorityOver('AUTH') -> returns(1) -> allowing($ext3)->getHandledKeyword() -> returns('STARTTLS') -> never($ext3)->getMailParams() -> ignoring($ext1) -> ignoring($ext2) -> ignoring($ext3) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3)); $smtp->start(); $smtp->send($message); } public function testExtensionsCanModifyRcptParams() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext3 = $this->_mock('Swift_Transport_EsmtpHandler'); $message = $this->_createMessage(); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> allowing($message)->getFrom() -> returns(array('me@domain'=>'Me')) -> allowing($message)->getTo() -> returns(array('foo@bar'=>null)) -> ignoring($message) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> one($buf)->write("MAIL FROM: \r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns("250 OK\r\n") -> one($buf)->write("RCPT TO: FOO ZIP\r\n") -> inSequence($s) -> returns(3) -> one($buf)->readLine(3) -> inSequence($s) -> returns("250 OK\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->getRcptParams() -> returns('FOO') -> allowing($ext1)->getPriorityOver('AUTH') -> returns(-1) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> one($ext2)->getRcptParams() -> returns('ZIP') -> allowing($ext2)->getPriorityOver('AUTH') -> returns(1) -> allowing($ext3)->getHandledKeyword() -> returns('STARTTLS') -> never($ext3)->getRcptParams() -> ignoring($ext1) -> ignoring($ext2) -> ignoring($ext3) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3)); $smtp->start(); $smtp->send($message); } public function testExtensionsAreNotifiedOnCommand() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext3 = $this->_mock('Swift_Transport_EsmtpHandler'); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> one($buf)->write("FOO\r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns("250 Cool\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->onCommand($smtp, "FOO\r\n", array(250, 251), optional()) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> one($ext2)->onCommand($smtp, "FOO\r\n", array(250, 251), optional()) -> allowing($ext3)->getHandledKeyword() -> returns('STARTTLS') -> never($ext3)->onCommand(any(), any(), any(), optional()) -> ignoring($ext1) -> ignoring($ext2) -> ignoring($ext3) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3)); $smtp->start(); $smtp->executeCommand("FOO\r\n", array(250, 251)); } public function testChainOfCommandAlgorithmWhenNotifyingExtensions() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $ext3 = $this->_mock('Swift_Transport_EsmtpHandler'); $s = $this->_sequence('Initiation-sequence'); $this->_checking(Expectations::create() -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 server.com foo\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-ServerName.tld\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250-AUTH PLAIN LOGIN\r\n") -> one($buf)->readLine(1) -> inSequence($s) -> returns("250 SIZE=123456\r\n") -> never($buf)->write("FOO\r\n") -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> one($ext1)->onCommand($smtp, "FOO\r\n", array(250, 251), optional()) -> calls(array($this, 'cbStopCommand')) -> allowing($ext2)->getHandledKeyword() -> returns('SIZE') -> never($ext2)->onCommand(any(), any(), any(), optional()) -> allowing($ext3)->getHandledKeyword() -> returns('STARTTLS') -> never($ext3)->onCommand(any(), any(), any(), optional()) -> ignoring($ext1) -> ignoring($ext2) -> ignoring($ext3) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2, $ext3)); $smtp->start(); $smtp->executeCommand("FOO\r\n", array(250, 251)); } public function cbStopCommand(Yay_Invocation $invocation) { $args =& $invocation->getArguments(); $stop =& $args[4]; $stop = true; return "250 ok"; } public function testExtensionsCanExposeMixinMethods() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandlerMixin'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $this->_checking(Expectations::create() -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> allowing($ext1)->exposeMixinMethods() -> returns(array('setUsername', 'setPassword')) -> one($ext1)->setUsername('mick') -> one($ext1)->setPassword('pass') -> allowing($ext2)->getHandledKeyword() -> returns('STARTTLS') -> ignoring($ext1) -> ignoring($ext2) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2)); $smtp->setUsername('mick'); $smtp->setPassword('pass'); } public function testMixinMethodsBeginningWithSetAndNullReturnAreFluid() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandlerMixin'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $this->_checking(Expectations::create() -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> allowing($ext1)->exposeMixinMethods() -> returns(array('setUsername', 'setPassword')) -> one($ext1)->setUsername('mick') -> returns(NULL) -> one($ext1)->setPassword('pass') -> returns(NULL) -> allowing($ext2)->getHandledKeyword() -> returns('STARTTLS') -> ignoring($ext1) -> ignoring($ext2) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2)); $ret = $smtp->setUsername('mick'); $this->assertReference($smtp, $ret); $ret = $smtp->setPassword('pass'); $this->assertReference($smtp, $ret); } public function testMixinSetterWhichReturnValuesAreNotFluid() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $ext1 = $this->_mock('Swift_Transport_EsmtpHandlerMixin'); $ext2 = $this->_mock('Swift_Transport_EsmtpHandler'); $this->_checking(Expectations::create() -> allowing($ext1)->getHandledKeyword() -> returns('AUTH') -> allowing($ext1)->exposeMixinMethods() -> returns(array('setUsername', 'setPassword')) -> one($ext1)->setUsername('mick') -> returns('x') -> one($ext1)->setPassword('pass') -> returns('x') -> allowing($ext2)->getHandledKeyword() -> returns('STARTTLS') -> ignoring($ext1) -> ignoring($ext2) ); $this->_finishBuffer($buf); $smtp->setExtensionHandlers(array($ext1, $ext2)); $this->assertEqual('x', $smtp->setUsername('mick')); $this->assertEqual('x', $smtp->setPassword('pass')); } } Swift-4.2.1/tests/unit/Swift/Transport/EsmtpTransportTest.php100644 0 0 22605 12000050367 21546 0ustar 0 0 _createEventDispatcher(); } return new Swift_Transport_EsmtpTransport($buf, array(), $dispatcher); } public function testHostCanBeSetAndFetched() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $smtp->setHost('foo'); $this->assertEqual('foo', $smtp->getHost(), '%s: Host should be returned'); } public function testPortCanBeSetAndFetched() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $smtp->setPort(25); $this->assertEqual(25, $smtp->getPort(), '%s: Port should be returned'); } public function testTimeoutCanBeSetAndFetched() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $this->_checking(Expectations::create() -> one($buf)->setParam('timeout', 10)); $smtp->setTimeout(10); $this->assertEqual(10, $smtp->getTimeout(), '%s: Timeout should be returned'); } public function testEncryptionCanBeSetAndFetched() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $smtp->setEncryption('tls'); $this->assertEqual('tls', $smtp->getEncryption(), '%s: Crypto should be returned'); } public function testStartSendsHeloToInitiate() {//Overridden for EHLO instead } public function testStartSendsEhloToInitiate() { /* -- RFC 2821, 3.2. 3.2 Client Initiation Once the server has sent the welcoming message and the client has received it, the client normally sends the EHLO command to the server, indicating the client's identity. In addition to opening the session, use of EHLO indicates that the client is able to process service extensions and requests that the server provide a list of the extensions it supports. Older SMTP systems which are unable to support service extensions and contemporary clients which do not require service extensions in the mail session being initiated, MAY use HELO instead of EHLO. Servers MUST NOT return the extended EHLO-style response to a HELO command. For a particular connection attempt, if the server returns a "command not recognized" response to EHLO, the client SHOULD be able to fall back and send HELO. In the EHLO command the host sending the command identifies itself; the command may be interpreted as saying "Hello, I am " (and, in the case of EHLO, "and I support service extension requests"). -- RFC 2281, 4.1.1.1. ehlo = "EHLO" SP Domain CRLF helo = "HELO" SP Domain CRLF -- RFC 2821, 4.3.2. EHLO or HELO S: 250 E: 504, 550 */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^EHLO .+?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('250 ServerName' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); } catch (Exception $e) { $this->fail('Starting Esmtp should send EHLO and accept 250 response'); } } public function testHeloIsUsedAsFallback() { /* -- RFC 2821, 4.1.4. If the EHLO command is not acceptable to the SMTP server, 501, 500, or 502 failure replies MUST be returned as appropriate. The SMTP server MUST stay in the same state after transmitting these replies that it was in before the EHLO was received. */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^EHLO .+?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('501 WTF' . "\r\n") -> one($buf)->write(pattern('~^HELO .+?\r\n$~D')) -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns('250 HELO' . "\r\n") ); $this->_finishBuffer($buf); try { $smtp->start(); } catch (Exception $e) { $this->fail( 'Starting Esmtp should fallback to HELO if needed and accept 250 response' ); } } public function testInvalidHeloResponseCausesException() {//Overridden to first try EHLO $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^EHLO .*?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('501 WTF' . "\r\n") -> one($buf)->write(pattern('~^HELO .*?\r\n$~D')) -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns('504 WTF' . "\r\n") ); $this->_finishBuffer($buf); try { $this->assertFalse($smtp->isStarted(), '%s: SMTP should begin non-started'); $smtp->start(); $this->fail('Non 250 HELO response should raise Exception'); } catch (Exception $e) { $this->assertFalse($smtp->isStarted(), '%s: SMTP start() should have failed'); } } public function testDomainNameIsPlacedInEhlo() { /* -- RFC 2821, 4.1.4. The SMTP client MUST, if possible, ensure that the domain parameter to the EHLO command is a valid principal host name (not a CNAME or MX name) for its host. If this is not possible (e.g., when the client's address is dynamically assigned and the client does not have an obvious name), an address literal SHOULD be substituted for the domain name and supplemental information provided that will assist in identifying the client. */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write("EHLO mydomain.com\r\n") -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('250 ServerName' . "\r\n") ); $this->_finishBuffer($buf); $smtp->setLocalDomain('mydomain.com'); $smtp->start(); } public function testDomainNameIsPlacedInHelo() { //Overridden to include ESMTP /* -- RFC 2821, 4.1.4. The SMTP client MUST, if possible, ensure that the domain parameter to the EHLO command is a valid principal host name (not a CNAME or MX name) for its host. If this is not possible (e.g., when the client's address is dynamically assigned and the client does not have an obvious name), an address literal SHOULD be substituted for the domain name and supplemental information provided that will assist in identifying the client. */ $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $s = $this->_sequence('SMTP-convo'); $this->_checking(Expectations::create() -> one($buf)->initialize() -> inSequence($s) -> one($buf)->readLine(0) -> inSequence($s) -> returns("220 some.server.tld bleh\r\n") -> one($buf)->write(pattern('~^EHLO .+?\r\n$~D')) -> inSequence($s) -> returns(1) -> one($buf)->readLine(1) -> inSequence($s) -> returns('501 WTF' . "\r\n") -> one($buf)->write("HELO mydomain.com\r\n") -> inSequence($s) -> returns(2) -> one($buf)->readLine(2) -> inSequence($s) -> returns('250 ServerName' . "\r\n") ); $this->_finishBuffer($buf); $smtp->setLocalDomain('mydomain.com'); $smtp->start(); } public function testFluidInterface() { $buf = $this->_getBuffer(); $smtp = $this->_getTransport($buf); $this->_checking(Expectations::create() -> one($buf)->setParam('timeout', 30)); $ref = $smtp ->setHost('foo') ->setPort(25) ->setEncryption('tls') ->setTimeout(30) ; $this->assertReference($ref, $smtp); } } Swift-4.2.1/tests/unit/Swift/Transport/FailoverTransportTest.php100644 0 0 35173 12000050367 22231 0ustar 0 0 mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> allowing($t1)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con->is('on')) -> one($t1)->start() -> when($con->isNot('on')) -> then($con->is('on')) -> one($t1)->send($message1, optional()) -> returns(1) -> when($con->is('on')) -> one($t1)->send($message2, optional()) -> returns(1) -> when($con->is('on')) -> ignoring($t1) -> never($t2)->start() -> never($t2)->send(any(), optional()) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message1)); $this->assertEqual(1, $transport->send($message2)); $context->assertIsSatisfied(); } public function testMessageCanBeTriedOnNextTransportIfExceptionThrown() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> returns(1) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message)); $context->assertIsSatisfied(); } public function testZeroIsReturnedIfTransportReturnsZero() { $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $con = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con->is('on')) -> one($t1)->start() -> when($con->isNot('on')) -> then($con->is('on')) -> one($t1)->send($message, optional()) -> returns(0) -> when($con->is('on')) -> ignoring($t1) ); $transport = $this->_getTransport(array($t1)); $transport->start(); $this->assertEqual(0, $transport->send($message)); $context->assertIsSatisfied(); } public function testTransportsWhichThrowExceptionsAreNotRetried() { $e = new Swift_TransportException('maur b0rken'); $context = new Mockery(); $message1 = $context->mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $message3 = $context->mock('Swift_Mime_Message'); $message4 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> ignoring($message3) -> ignoring($message4) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> throws($e) -> when($con1->is('on')) -> never($t1)->send($message2, optional()) -> never($t1)->send($message3, optional()) -> never($t1)->send($message4, optional()) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message1, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message2, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message3, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message4, optional()) -> returns(1) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message1)); $this->assertEqual(1, $transport->send($message2)); $this->assertEqual(1, $transport->send($message3)); $this->assertEqual(1, $transport->send($message4)); } public function testExceptionIsThrownIfAllTransportsDie() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> throws($e) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); try { $transport->send($message); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { } $context->assertIsSatisfied(); } public function testStoppingTransportStopsAllDelegates() { $context = new Mockery(); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('on'); $con2 = $context->states('Connection')->startsAs('on'); $context->checking(Expectations::create() -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->stop() -> when($con1->is('on')) -> then($con1->is('off')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->stop() -> when($con2->is('on')) -> then($con2->is('off')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $transport->stop(); $context->assertIsSatisfied(); } public function testTransportShowsAsNotStartedIfAllDelegatesDead() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> throws($e) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertTrue($transport->isStarted()); try { $transport->send($message); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { $this->assertFalse($transport->isStarted()); } $context->assertIsSatisfied(); } public function testRestartingTransportRestartsDeadDelegates() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message1 = $context->mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> exactly(2)->of($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> throws($e) -> when($con1->is('on')) -> then($con1->is('off')) -> one($t1)->send($message2, optional()) -> returns(10) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message1, optional()) -> throws($e) -> when($con2->is('on')) -> never($t2)->send($message2, optional()) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertTrue($transport->isStarted()); try { $transport->send($message1); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { $this->assertFalse($transport->isStarted()); } //Restart and re-try $transport->start(); $this->assertTrue($transport->isStarted()); $this->assertEqual(10, $transport->send($message2)); $context->assertIsSatisfied(); } public function testFailureReferenceIsPassedToDelegates() { $failures = array(); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $con = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con->is('on')) -> one($t1)->start() -> when($con->isNot('on')) -> then($con->is('on')) -> one($t1)->send($message, reference($failures)) -> returns(1) -> when($con->is('on')) -> ignoring($t1) ); $transport = $this->_getTransport(array($t1)); $transport->start(); $transport->send($message, $failures); $context->assertIsSatisfied(); } public function testRegisterPluginDelegatesToLoadedTransports() { $context = new Mockery(); $plugin = $this->_createPlugin($context); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $context->checking(Expectations::create() -> one($t1)->registerPlugin($plugin) -> one($t2)->registerPlugin($plugin) -> ignoring($t1) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->registerPlugin($plugin); $context->assertIsSatisfied(); } // -- Private helpers private function _getTransport(array $transports) { $transport = new Swift_Transport_FailoverTransport(); $transport->setTransports($transports); return $transport; } private function _createPlugin($context) { return $context->mock('Swift_Events_EventListener'); } private function _createInnerTransport() { return $this->_mockery()->mock('Swift_Transport'); } } Swift-4.2.1/tests/unit/Swift/Transport/LoadBalancedTransportTest.php100644 0 0 46124 12000050367 22751 0ustar 0 0 mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection 1')->startsAs('off'); $con2 = $context->states('Connection 2')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> allowing($t1)->start() -> when($con1->is('off')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> returns(1) -> when($con1->is('on')) -> never($t1)->send($message2, optional()) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> allowing($t2)->start() -> when($con2->is('off')) -> then($con2->is('on')) -> one($t2)->send($message2, optional()) -> returns(1) -> when($con2->is('on')) -> never($t2)->send($message1, optional()) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message1)); $this->assertEqual(1, $transport->send($message2)); $context->assertIsSatisfied(); } public function testTransportsAreReusedInRotatingFashion() { $context = new Mockery(); $message1 = $context->mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $message3 = $context->mock('Swift_Mime_Message'); $message4 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection 1')->startsAs('off'); $con2 = $context->states('Connection 2')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> allowing($t1)->start() -> when($con1->is('off')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> returns(1) -> when($con1->is('on')) -> never($t1)->send($message2, optional()) -> one($t1)->send($message3, optional()) -> returns(1) -> when($con1->is('on')) -> never($t1)->send($message4, optional()) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> allowing($t2)->start() -> when($con2->is('off')) -> then($con2->is('on')) -> one($t2)->send($message2, optional()) -> returns(1) -> when($con2->is('on')) -> never($t2)->send($message1, optional()) -> one($t2)->send($message4, optional()) -> returns(1) -> when($con2->is('on')) -> never($t2)->send($message3, optional()) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message1)); $this->assertEqual(1, $transport->send($message2)); $this->assertEqual(1, $transport->send($message3)); $this->assertEqual(1, $transport->send($message4)); $context->assertIsSatisfied(); } public function testMessageCanBeTriedOnNextTransportIfExceptionThrown() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> returns(1) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message)); $context->assertIsSatisfied(); } public function testMessageIsTriedOnNextTransportIfZeroReturned() { $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> returns(0) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> returns(1) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message)); $context->assertIsSatisfied(); } public function testZeroIsReturnedIfAllTransportsReturnZero() { $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> returns(0) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> returns(0) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(0, $transport->send($message)); $context->assertIsSatisfied(); } public function testTransportsWhichThrowExceptionsAreNotRetried() { $e = new Swift_TransportException('maur b0rken'); $context = new Mockery(); $message1 = $context->mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $message3 = $context->mock('Swift_Mime_Message'); $message4 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> ignoring($message3) -> ignoring($message4) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> throws($e) -> when($con1->is('on')) -> never($t1)->send($message2, optional()) -> never($t1)->send($message3, optional()) -> never($t1)->send($message4, optional()) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message1, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message2, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message3, optional()) -> returns(1) -> when($con2->is('on')) -> one($t2)->send($message4, optional()) -> returns(1) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertEqual(1, $transport->send($message1)); $this->assertEqual(1, $transport->send($message2)); $this->assertEqual(1, $transport->send($message3)); $this->assertEqual(1, $transport->send($message4)); } public function testExceptionIsThrownIfAllTransportsDie() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> throws($e) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); try { $transport->send($message); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { } $context->assertIsSatisfied(); } public function testStoppingTransportStopsAllDelegates() { $context = new Mockery(); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('on'); $con2 = $context->states('Connection')->startsAs('on'); $context->checking(Expectations::create() -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->stop() -> when($con1->is('on')) -> then($con1->is('off')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->stop() -> when($con2->is('on')) -> then($con2->is('off')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $transport->stop(); $context->assertIsSatisfied(); } public function testTransportShowsAsNotStartedIfAllDelegatesDead() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> one($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message, optional()) -> throws($e) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message, optional()) -> throws($e) -> when($con2->is('on')) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertTrue($transport->isStarted()); try { $transport->send($message); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { $this->assertFalse($transport->isStarted()); } $context->assertIsSatisfied(); } public function testRestartingTransportRestartsDeadDelegates() { $e = new Swift_TransportException('b0rken'); $context = new Mockery(); $message1 = $context->mock('Swift_Mime_Message'); $message2 = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $con1 = $context->states('Connection')->startsAs('off'); $con2 = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message1) -> ignoring($message2) -> allowing($t1)->isStarted() -> returns(false) -> when($con1->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con1->is('on')) -> exactly(2)->of($t1)->start() -> when($con1->isNot('on')) -> then($con1->is('on')) -> one($t1)->send($message1, optional()) -> throws($e) -> when($con1->is('on')) -> then($con1->is('off')) -> one($t1)->send($message2, optional()) -> returns(10) -> when($con1->is('on')) -> ignoring($t1) -> allowing($t2)->isStarted() -> returns(false) -> when($con2->is('off')) -> allowing($t2)->isStarted() -> returns(true) -> when($con2->is('on')) -> one($t2)->start() -> when($con2->isNot('on')) -> then($con2->is('on')) -> one($t2)->send($message1, optional()) -> throws($e) -> when($con2->is('on')) -> never($t2)->send($message2, optional()) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->start(); $this->assertTrue($transport->isStarted()); try { $transport->send($message1); $this->fail('All transports failed so Exception should be thrown'); } catch (Exception $e) { $this->assertFalse($transport->isStarted()); } //Restart and re-try $transport->start(); $this->assertTrue($transport->isStarted()); $this->assertEqual(10, $transport->send($message2)); $context->assertIsSatisfied(); } public function testFailureReferenceIsPassedToDelegates() { $failures = array(); $context = new Mockery(); $message = $context->mock('Swift_Mime_Message'); $t1 = $context->mock('Swift_Transport'); $con = $context->states('Connection')->startsAs('off'); $context->checking(Expectations::create() -> ignoring($message) -> allowing($t1)->isStarted() -> returns(false) -> when($con->is('off')) -> allowing($t1)->isStarted() -> returns(true) -> when($con->is('on')) -> one($t1)->start() -> when($con->isNot('on')) -> then($con->is('on')) -> one($t1)->send($message, reference($failures)) -> returns(1) -> when($con->is('on')) -> ignoring($t1) ); $transport = $this->_getTransport(array($t1)); $transport->start(); $transport->send($message, $failures); $context->assertIsSatisfied(); } public function testRegisterPluginDelegatesToLoadedTransports() { $context = new Mockery(); $plugin = $this->_createPlugin($context); $t1 = $context->mock('Swift_Transport'); $t2 = $context->mock('Swift_Transport'); $context->checking(Expectations::create() -> one($t1)->registerPlugin($plugin) -> one($t2)->registerPlugin($plugin) -> ignoring($t1) -> ignoring($t2) ); $transport = $this->_getTransport(array($t1, $t2)); $transport->registerPlugin($plugin); $context->assertIsSatisfied(); } // -- Private helpers private function _getTransport(array $transports) { $transport = new Swift_Transport_LoadBalancedTransport(); $transport->setTransports($transports); return $transport; } private function _createPlugin($context) { return $context->mock('Swift_Events_EventListener'); } private function _createInnerTransport() { return $this->_mockery()->mock('Swift_Transport'); } }Swift-4.2.1/tests/unit/Swift/Transport/MailTransportTest.php100644 0 0 24100 12000050367 21330 0ustar 0 0 _createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $headers = $this->_createHeaders(); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) ); $transport->send($message); } public function testTransportUsesToFieldBodyInSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $to = $this->_createHeader(); $headers = $this->_createHeaders(array( 'To' => $to )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($to)->getFieldBody() -> returns("Foo ") -> one($invoker)->mail("Foo ", any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($to) ); $transport->send($message); } public function testTransportUsesSubjectFieldBodyInSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $subj = $this->_createHeader(); $headers = $this->_createHeaders(array( 'Subject' => $subj )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($subj)->getFieldBody() -> returns("Thing") -> one($invoker)->mail(any(), "Thing", any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($subj) ); $transport->send($message); } public function testTransportUsesBodyOfMessage() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $headers = $this->_createHeaders(); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($message)->toString() -> returns( "To: Foo \r\n" . "\r\n" . "This body" ) -> one($invoker)->mail(any(), any(), "This body", any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) ); $transport->send($message); } public function testTransportUsesHeadersFromMessage() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $headers = $this->_createHeaders(); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($message)->toString() -> returns( "Subject: Stuff\r\n" . "\r\n" . "This body" ) -> one($invoker)->mail(any(), any(), any(), "Subject: Stuff" . PHP_EOL, optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) ); $transport->send($message); } public function testTransportReturnsCountOfAllRecipientsIfInvokerReturnsTrue() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $headers = $this->_createHeaders(); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>null, 'zip@button'=>null)) -> allowing($message)->getCc() -> returns(array('test@test'=>null)) -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> returns(true) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) ); $this->assertEqual(3, $transport->send($message)); } public function testTransportReturnsZeroIfInvokerReturnsFalse() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $headers = $this->_createHeaders(); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>null, 'zip@button'=>null)) -> allowing($message)->getCc() -> returns(array('test@test'=>null)) -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> returns(false) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) ); $this->assertEqual(0, $transport->send($message)); } public function testToHeaderIsRemovedFromHeaderSetDuringSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $to = $this->_createHeader(); $headers = $this->_createHeaders(array( 'To' => $to )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> one($headers)->remove('To') -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($to) ); $transport->send($message); } public function testSubjectHeaderIsRemovedFromHeaderSetDuringSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $subject = $this->_createHeader(); $headers = $this->_createHeaders(array( 'Subject' => $subject )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> one($headers)->remove('Subject') -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($subject) ); $transport->send($message); } public function testToHeaderIsPutBackAfterSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $to = $this->_createHeader(); $headers = $this->_createHeaders(array( 'To' => $to )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> one($headers)->set($to, optional()) -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($to) ); $transport->send($message); } public function testSubjectHeaderIsPutBackAfterSending() { $invoker = $this->_createInvoker(); $dispatcher = $this->_createEventDispatcher(); $transport = $this->_createTransport($invoker, $dispatcher); $subject = $this->_createHeader(); $headers = $this->_createHeaders(array( 'Subject' => $subject )); $message = $this->_createMessage($headers); $this->_checking(Expectations::create() -> one($headers)->set($subject, optional()) -> one($invoker)->mail(any(), any(), any(), any(), optional()) -> ignoring($dispatcher) -> ignoring($headers) -> ignoring($message) -> ignoring($subject) ); $transport->send($message); } // -- Creation Methods private function _createTransport($invoker, $dispatcher) { return new Swift_Transport_MailTransport($invoker, $dispatcher); } private function _createEventDispatcher() { return $this->_mock('Swift_Events_EventDispatcher'); } private function _createInvoker() { return $this->_mock('Swift_Transport_MailInvoker'); } private function _createMessage($headers) { $message = $this->_mock('Swift_Mime_Message'); $this->_checking(Expectations::create() -> allowing($message)->getHeaders() -> returns($headers) ); return $message; } private function _createHeaders($headers = array()) { $set = $this->_mock('Swift_Mime_HeaderSet'); if (count($headers) > 0) { foreach ($headers as $name => $header) { $this->_checking(Expectations::create() -> allowing($set)->get($name) -> returns($header) -> allowing($set)->has($name) -> returns(true) ); } } $header = $this->_createHeader(); $this->_checking(Expectations::create() -> allowing($set)->get(any()) -> returns($header) -> allowing($set)->has(any()) -> returns(true) -> ignoring($header) ); return $set; } private function _createHeader() { return $this->_mock('Swift_Mime_Header'); } } Swift-4.2.1/tests/unit/Swift/Transport/SendmailTransportTest.php100644 0 0 11370 12000050367 22207 0ustar 0 0 _createEventDispatcher(); } $transport = new Swift_Transport_SendmailTransport($buf, $dispatcher); $transport->setCommand($command); return $transport; } protected function _getSendmail($buf, $dispatcher = null) { if (!$dispatcher) { $dispatcher = $this->_createEventDispatcher(); } $sendmail = new Swift_Transport_SendmailTransport($buf, $dispatcher); return $sendmail; } public function testCommandCanBeSetAndFetched() { $buf = $this->_getBuffer(); $sendmail = $this->_getSendmail($buf); $sendmail->setCommand('/usr/sbin/sendmail -bs'); $this->assertEqual('/usr/sbin/sendmail -bs', $sendmail->getCommand()); $sendmail->setCommand('/usr/sbin/sendmail -oi -t'); $this->assertEqual('/usr/sbin/sendmail -oi -t', $sendmail->getCommand()); } public function testSendingMessageIn_t_ModeUsesSimplePipe() { $buf = $this->_getBuffer(); $sendmail = $this->_getSendmail($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>'Foobar', 'zip@button'=>'Zippy')) -> one($message)->toByteStream($buf) -> ignoring($message) -> one($buf)->initialize() -> one($buf)->terminate() -> one($buf)->setWriteTranslations(array("\r\n"=>"\n", "\n." => "\n..")) -> one($buf)->setWriteTranslations(array()) -> ignoring($buf) ); $sendmail->setCommand('/usr/sbin/sendmail -t'); $this->assertEqual(2, $sendmail->send($message)); } public function testSendingIn_t_ModeWith_i_FlagDoesntEscapeDot() { $buf = $this->_getBuffer(); $sendmail = $this->_getSendmail($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>'Foobar', 'zip@button'=>'Zippy')) -> one($message)->toByteStream($buf) -> ignoring($message) -> one($buf)->initialize() -> one($buf)->terminate() -> one($buf)->setWriteTranslations(array("\r\n"=>"\n")) -> one($buf)->setWriteTranslations(array()) -> ignoring($buf) ); $sendmail->setCommand('/usr/sbin/sendmail -i -t'); $this->assertEqual(2, $sendmail->send($message)); } public function testSendingInTModeWith_oi_FlagDoesntEscapeDot() { $buf = $this->_getBuffer(); $sendmail = $this->_getSendmail($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>'Foobar', 'zip@button'=>'Zippy')) -> one($message)->toByteStream($buf) -> ignoring($message) -> one($buf)->initialize() -> one($buf)->terminate() -> one($buf)->setWriteTranslations(array("\r\n"=>"\n")) -> one($buf)->setWriteTranslations(array()) -> ignoring($buf) ); $sendmail->setCommand('/usr/sbin/sendmail -oi -t'); $this->assertEqual(2, $sendmail->send($message)); } public function testSendingMessageRegeneratesId() { $buf = $this->_getBuffer(); $sendmail = $this->_getSendmail($buf); $message = $this->_createMessage(); $this->_checking(Expectations::create() -> allowing($message)->getTo() -> returns(array('foo@bar'=>'Foobar', 'zip@button'=>'Zippy')) -> one($message)->generateId() -> ignoring($message) -> one($buf)->initialize() -> one($buf)->terminate() -> one($buf)->setWriteTranslations(array("\r\n"=>"\n", "\n." => "\n..")) -> one($buf)->setWriteTranslations(array()) -> ignoring($buf) ); $sendmail->setCommand('/usr/sbin/sendmail -t'); $this->assertEqual(2, $sendmail->send($message)); } public function testFluidInterface() { $buf = $this->_getBuffer(); $sendmail = $this->_getTransport($buf); $ref = $sendmail->setCommand('/foo'); $this->assertReference($ref, $sendmail); } } Swift-4.2.1/tests/unit/Swift/Transport/StreamBufferTest.php100644 0 0 3156 12000050367 21106 0ustar 0 0 _createFactory(); $this->_checking(Expectations::create() -> one($factory)->createFilter('a', 'b') -> returns($this->_createFilter()) -> never($factory) ); $buffer = $this->_createBuffer($factory); $buffer->setWriteTranslations(array('a' => 'b')); } public function testOverridingTranslationsOnlyAddsNeededFilters() { $factory = $this->_createFactory(); $this->_checking(Expectations::create() -> one($factory)->createFilter('a', 'b') -> returns($this->_createFilter()) -> one($factory)->createFilter('x', 'y') -> returns($this->_createFilter()) -> never($factory) ); $buffer = $this->_createBuffer($factory); $buffer->setWriteTranslations(array('a' => 'b')); $buffer->setWriteTranslations(array('x' => 'y', 'a' => 'b')); } // -- Creation methods private function _createBuffer($replacementFactory) { return new Swift_Transport_StreamBuffer($replacementFactory); } private function _createFactory() { return $this->_mock('Swift_ReplacementFilterFactory'); } private function _createFilter() { return $this->_stub('Swift_StreamFilter'); } }