PageRenderTime 26ms CodeModel.GetById 18ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/system/vendor/Swift/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php

https://bitbucket.org/horvelod/easymynewsletter
PHP | 223 lines | 144 code | 29 blank | 50 comment | 6 complexity | d4519a3caf59cd5b75c63a3b99ed69c3 MD5 | raw file
  1<?php
  2
  3require_once 'Swift/Tests/SwiftUnitTestCase.php';
  4require_once 'Swift/Mime/HeaderEncoder/QpHeaderEncoder.php';
  5require_once 'Swift/CharacterStream.php';
  6
  7class Swift_Mime_HeaderEncoder_QpHeaderEncoderTest
  8    extends Swift_Tests_SwiftUnitTestCase
  9{
 10    //Most tests are already covered in QpEncoderTest since this subclass only
 11    // adds a getName() method
 12
 13    public function testNameIsQ()
 14    {
 15        $encoder = $this->_createEncoder(
 16            $this->_createCharacterStream(true)
 17            );
 18        $this->assertEqual('Q', $encoder->getName());
 19    }
 20
 21    public function testSpaceAndTabNeverAppear()
 22    {
 23        /* -- RFC 2047, 4.
 24     Only a subset of the printable ASCII characters may be used in
 25     'encoded-text'.  Space and tab characters are not allowed, so that
 26     the beginning and end of an 'encoded-word' are obvious.
 27     */
 28
 29        $charStream = $this->_createCharacterStream();
 30        $this->_checking(Expectations::create()
 31            -> one($charStream)->readBytes(any()) -> returns(array(ord('a')))
 32            -> one($charStream)->readBytes(any()) -> returns(array(0x20))
 33            -> one($charStream)->readBytes(any()) -> returns(array(0x09))
 34            -> one($charStream)->readBytes(any()) -> returns(array(0x20))
 35            -> one($charStream)->readBytes(any()) -> returns(array(ord('b')))
 36            -> allowing($charStream)->readBytes(any()) -> returns(false)
 37            -> ignoring($charStream)
 38            );
 39
 40        $encoder = $this->_createEncoder($charStream);
 41        $this->assertNoPattern('~[ \t]~', $encoder->encodeString("a \t b"),
 42            '%s: encoded-words in headers cannot contain LWSP as per RFC 2047.'
 43            );
 44    }
 45
 46    public function testSpaceIsRepresentedByUnderscore()
 47    {
 48        /* -- RFC 2047, 4.2.
 49        (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
 50       represented as "_" (underscore, ASCII 95.).  (This character may
 51       not pass through some internetwork mail gateways, but its use
 52       will greatly enhance readability of "Q" encoded data with mail
 53       readers that do not support this encoding.)  Note that the "_"
 54       always represents hexadecimal 20, even if the SPACE character
 55       occupies a different code position in the character set in use.
 56       */
 57        $charStream = $this->_createCharacterStream();
 58        $this->_checking(Expectations::create()
 59            -> one($charStream)->readBytes(any()) -> returns(array(ord('a')))
 60            -> one($charStream)->readBytes(any()) -> returns(array(0x20))
 61            -> one($charStream)->readBytes(any()) -> returns(array(ord('b')))
 62            -> allowing($charStream)->readBytes(any()) -> returns(false)
 63            -> ignoring($charStream)
 64            );
 65
 66        $encoder = $this->_createEncoder($charStream);
 67        $this->assertEqual('a_b', $encoder->encodeString('a b'),
 68            '%s: Spaces can be represented by more readable underscores as per RFC 2047.'
 69            );
 70    }
 71
 72    public function testEqualsAndQuestionAndUnderscoreAreEncoded()
 73    {
 74        /* -- RFC 2047, 4.2.
 75        (3) 8-bit values which correspond to printable ASCII characters other
 76       than "=", "?", and "_" (underscore), MAY be represented as those
 77       characters.  (But see section 5 for restrictions.)  In
 78       particular, SPACE and TAB MUST NOT be represented as themselves
 79       within encoded words.
 80       */
 81        $charStream = $this->_createCharacterStream();
 82        $this->_checking(Expectations::create()
 83            -> one($charStream)->readBytes(any()) -> returns(array(ord('=')))
 84            -> one($charStream)->readBytes(any()) -> returns(array(ord('?')))
 85            -> one($charStream)->readBytes(any()) -> returns(array(ord('_')))
 86            -> allowing($charStream)->readBytes(any()) -> returns(false)
 87            -> ignoring($charStream)
 88            );
 89
 90        $encoder = $this->_createEncoder($charStream);
 91        $this->assertEqual('=3D=3F=5F', $encoder->encodeString('=?_'),
 92            '%s: Chars =, ? and _ (underscore) may not appear as per RFC 2047.'
 93            );
 94    }
 95
 96    public function testParensAndQuotesAreEncoded()
 97    {
 98        /* -- RFC 2047, 5 (2).
 99     A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT
100     contain the characters "(", ")" or "
101     */
102
103        $charStream = $this->_createCharacterStream();
104        $this->_checking(Expectations::create()
105            -> one($charStream)->readBytes(any()) -> returns(array(ord('(')))
106            -> one($charStream)->readBytes(any()) -> returns(array(ord('"')))
107            -> one($charStream)->readBytes(any()) -> returns(array(ord(')')))
108            -> allowing($charStream)->readBytes(any()) -> returns(false)
109            -> ignoring($charStream)
110            );
111
112        $encoder = $this->_createEncoder($charStream);
113        $this->assertEqual('=28=22=29', $encoder->encodeString('(")'),
114            '%s: Chars (, " (DQUOTE) and ) may not appear as per RFC 2047.'
115            );
116    }
117
118    public function testOnlyCharactersAllowedInPhrasesAreUsed()
119    {
120        /* -- RFC 2047, 5.
121        (3) As a replacement for a 'word' entity within a 'phrase', for example,
122        one that precedes an address in a From, To, or Cc header.  The ABNF
123        definition for 'phrase' from RFC 822 thus becomes:
124
125        phrase = 1*( encoded-word / word )
126
127        In this case the set of characters that may be used in a "Q"-encoded
128        'encoded-word' is restricted to: <upper and lower case ASCII
129        letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
130        (underscore, ASCII 95.)>.  An 'encoded-word' that appears within a
131        'phrase' MUST be separated from any adjacent 'word', 'text' or
132        'special' by 'linear-white-space'.
133        */
134
135        $allowedBytes = array_merge(
136            range(ord('a'), ord('z')), range(ord('A'), ord('Z')),
137            range(ord('0'), ord('9')),
138            array(ord('!'), ord('*'), ord('+'), ord('-'), ord('/'))
139            );
140
141        foreach (range(0x00, 0xFF) as $byte) {
142            $char = pack('C', $byte);
143
144            $charStream = $this->_createCharacterStream();
145            $this->_checking(Expectations::create()
146                -> one($charStream)->readBytes(any()) -> returns(array($byte))
147                -> allowing($charStream)->readBytes(any()) -> returns(false)
148                -> ignoring($charStream)
149                );
150
151            $encoder = $this->_createEncoder($charStream);
152            $encodedChar = $encoder->encodeString($char);
153
154            if (in_array($byte, $allowedBytes)) {
155                $this->assertEqual($char, $encodedChar,
156                    '%s: Character ' . $char . ' should not be encoded.'
157                    );
158            }
159            elseif (0x20 == $byte) //Special case
160            {
161                $this->assertEqual('_', $encodedChar,
162                    '%s: Space character should be replaced.'
163                    );
164            } else {
165                $this->assertEqual(sprintf('=%02X', $byte), $encodedChar,
166                    '%s: Byte ' . $byte . ' should be encoded.'
167                    );
168            }
169        }
170    }
171
172    public function testEqualsNeverAppearsAtEndOfLine()
173    {
174        /* -- RFC 2047, 5 (3).
175        The 'encoded-text' in an 'encoded-word' must be self-contained;
176        'encoded-text' MUST NOT be continued from one 'encoded-word' to
177        another.  This implies that the 'encoded-text' portion of a "B"
178        'encoded-word' will be a multiple of 4 characters long; for a "Q"
179        'encoded-word', any "=" character that appears in the 'encoded-text'
180        portion will be followed by two hexadecimal characters.
181        */
182
183        $input = str_repeat('a', 140);
184
185        $charStream = $this->_createCharacterStream();
186
187        $output = '';
188        $seq = 0;
189        for (; $seq < 140; ++$seq) {
190            $this->_checking(Expectations::create()
191                -> one($charStream)->readBytes(any()) -> returns(array(ord('a')))
192                );
193
194            if (75 == $seq) {
195                $output .= "\r\n"; // =\r\n
196            }
197            $output .= 'a';
198        }
199
200        $this->_checking(Expectations::create()
201            -> allowing($charStream)->readBytes(any()) -> returns(false)
202            -> ignoring($charStream)
203            );
204
205        $encoder = $this->_createEncoder($charStream);
206        $this->assertEqual($output, $encoder->encodeString($input));
207    }
208
209    // -- Creation Methods
210
211    private function _createEncoder($charStream)
212    {
213        return new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream);
214    }
215
216    private function _createCharacterStream($stub = false)
217    {
218        return $stub
219            ? $this->_stub('Swift_CharacterStream')
220            : $this->_mock('Swift_CharacterStream')
221            ;
222    }
223}