_specials = array( '(', ')', '<', '>', '[', ']', ':', ';', '@', ',', '.', '"' ); /*** Refer to RFC 2822 for ABNF grammar ***/ //All basic building blocks $this->_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]'; $this->_grammar['WSP'] = '[ \t]'; $this->_grammar['CRLF'] = '(?:\r\n)'; $this->_grammar['FWS'] = '(?:(?:' . $this->_grammar['WSP'] . '*' . $this->_grammar['CRLF'] . ')?' . $this->_grammar['WSP'] . ')'; $this->_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]'; $this->_grammar['quoted-pair'] = '(?:\\\\' . $this->_grammar['text'] . ')'; $this->_grammar['ctext'] = '(?:' . $this->_grammar['NO-WS-CTL'] . '|[\x21-\x27\x2A-\x5B\x5D-\x7E])'; //Uses recursive PCRE (?1) -- could be a weak point?? $this->_grammar['ccontent'] = '(?:' . $this->_grammar['ctext'] . '|' . $this->_grammar['quoted-pair'] . '|(?1))'; $this->_grammar['comment'] = '(\((?:' . $this->_grammar['FWS'] . '|' . $this->_grammar['ccontent']. ')*' . $this->_grammar['FWS'] . '?\))'; $this->_grammar['CFWS'] = '(?:(?:' . $this->_grammar['FWS'] . '?' . $this->_grammar['comment'] . ')*(?:(?:' . $this->_grammar['FWS'] . '?' . $this->_grammar['comment'] . ')|' . $this->_grammar['FWS'] . '))'; $this->_grammar['qtext'] = '(?:' . $this->_grammar['NO-WS-CTL'] . '|[\x21\x23-\x5B\x5D-\x7E])'; $this->_grammar['qcontent'] = '(?:' . $this->_grammar['qtext'] . '|' . $this->_grammar['quoted-pair'] . ')'; $this->_grammar['quoted-string'] = '(?:' . $this->_grammar['CFWS'] . '?"' . '(' . $this->_grammar['FWS'] . '?' . $this->_grammar['qcontent'] . ')*' . $this->_grammar['FWS'] . '?"' . $this->_grammar['CFWS'] . '?)'; $this->_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]'; $this->_grammar['atom'] = '(?:' . $this->_grammar['CFWS'] . '?' . $this->_grammar['atext'] . '+' . $this->_grammar['CFWS'] . '?)'; $this->_grammar['dot-atom-text'] = '(?:' . $this->_grammar['atext'] . '+' . '(\.' . $this->_grammar['atext'] . '+)*)'; $this->_grammar['dot-atom'] = '(?:' . $this->_grammar['CFWS'] . '?' . $this->_grammar['dot-atom-text'] . '+' . $this->_grammar['CFWS'] . '?)'; $this->_grammar['word'] = '(?:' . $this->_grammar['atom'] . '|' . $this->_grammar['quoted-string'] . ')'; $this->_grammar['phrase'] = '(?:' . $this->_grammar['word'] . '+?)'; $this->_grammar['no-fold-quote'] = '(?:"(?:' . $this->_grammar['qtext'] . '|' . $this->_grammar['quoted-pair'] . ')*")'; $this->_grammar['dtext'] = '(?:' . $this->_grammar['NO-WS-CTL'] . '|[\x21-\x5A\x5E-\x7E])'; $this->_grammar['no-fold-literal'] = '(?:\[(?:' . $this->_grammar['dtext'] . '|' . $this->_grammar['quoted-pair'] . ')*\])'; //Message IDs $this->_grammar['id-left'] = '(?:' . $this->_grammar['dot-atom-text'] . '|' . $this->_grammar['no-fold-quote'] . ')'; $this->_grammar['id-right'] = '(?:' . $this->_grammar['dot-atom-text'] . '|' . $this->_grammar['no-fold-literal'] . ')'; //Addresses, mailboxes and paths $this->_grammar['local-part'] = '(?:' . $this->_grammar['dot-atom'] . '|' . $this->_grammar['quoted-string'] . ')'; $this->_grammar['dcontent'] = '(?:' . $this->_grammar['dtext'] . '|' . $this->_grammar['quoted-pair'] . ')'; $this->_grammar['domain-literal'] = '(?:' . $this->_grammar['CFWS'] . '?\[(' . $this->_grammar['FWS'] . '?' . $this->_grammar['dcontent'] . ')*?' . $this->_grammar['FWS'] . '?\]' . $this->_grammar['CFWS'] . '?)'; $this->_grammar['domain'] = '(?:' . $this->_grammar['dot-atom'] . '|' . $this->_grammar['domain-literal'] . ')'; $this->_grammar['addr-spec'] = '(?:' . $this->_grammar['local-part'] . '@' . $this->_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, $this->_grammar)) { return $this->_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 $this->_grammar; } /** * Returns the current special characters used in the syntax which need to be escaped. * @return array */ public function getSpecials() { return $this->_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($this->_specials, $exclude), $include) as $char) { $token = str_replace($char, '\\' . $char, $token); } return $token; } }