[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/horde/framework/Horde/Imap/Client/Data/ -> BaseSubject.php (source)

   1  <?php
   2  /**
   3   * Copyright 2008-2014 Horde LLC (http://www.horde.org/)
   4   *
   5   * getBaseSubject() code adapted from imap-base-subject.c (Dovecot 1.2)
   6   *   Original code released under the LGPL-2.1
   7   *   Copyright (c) 2002-2008 Timo Sirainen <tss@iki.fi>
   8   *
   9   * See the enclosed file COPYING for license information (LGPL). If you
  10   * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  11   *
  12   * @category  Horde
  13   * @copyright 2002-2008 Timo Sirainen
  14   * @copyright 2008-2014 Horde LLC
  15   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  16   * @package   Imap_Client
  17   */
  18  
  19  /**
  20   * Determines the "base subject" of a string (RFC 5256 [2.1]).
  21   *
  22   * @author    Timo Sirainen <tss@iki.fi>
  23   * @author    Michael Slusarz <slusarz@horde.org>
  24   * @category  Horde
  25   * @copyright 2002-2008 Timo Sirainen
  26   * @copyright 2011-2014 Horde LLC
  27   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  28   * @package   Imap_Client
  29   */
  30  class Horde_Imap_Client_Data_BaseSubject
  31  {
  32      /**
  33       * The base subject.
  34       *
  35       * @var string
  36       */
  37      protected $_subject;
  38  
  39      /**
  40       * Constructor.
  41       *
  42       * @param string $str  The subject string.
  43       * @param array $opts  Additional options:
  44       *   - keepblob: (boolean) Don't remove any "blob" information (i.e. text
  45       *               leading text between square brackets) from string.
  46       *
  47       * @return string  The cleaned up subject string.
  48       */
  49      public function __construct($str, array $opts = array())
  50      {
  51          // Rule 1a: MIME decode.
  52          $str = Horde_Mime::decode($str);
  53  
  54          // Rule 1b: Remove superfluous whitespace.
  55          $str = preg_replace("/[\t\r\n ]+/", ' ', $str);
  56  
  57          do {
  58              /* (2) Remove all trailing text of the subject that matches the
  59               * the subj-trailer ABNF, repeat until no more matches are
  60               * possible. */
  61              $str = preg_replace("/(?:\s*\(fwd\)\s*)+$/i", '', $str);
  62  
  63              do {
  64                  /* (3) Remove all prefix text of the subject that matches the
  65                   * subj-leader ABNF. */
  66                  $found = $this->_removeSubjLeader($str, !empty($opts['keepblob']));
  67  
  68                  /* (4) If there is prefix text of the subject that matches
  69                   * the subj-blob ABNF, and removing that prefix leaves a
  70                   * non-empty subj-base, then remove the prefix text. */
  71                  $found = (empty($opts['keepblob']) && $this->_removeBlobWhenNonempty($str)) || $found;
  72  
  73                  /* (5) Repeat (3) and (4) until no matches remain. */
  74              } while ($found);
  75  
  76              /* (6) If the resulting text begins with the subj-fwd-hdr ABNF and
  77               * ends with the subj-fwd-trl ABNF, remove the subj-fwd-hdr and
  78               * subj-fwd-trl and repeat from step (2). */
  79          } while ($this->_removeSubjFwdHdr($str));
  80  
  81          $this->_subject = strval($str);
  82      }
  83  
  84      /**
  85       * Return the "base subject" defined in RFC 5256 [2.1].
  86       *
  87       * @return string  The base subject.
  88       */
  89      public function __toString()
  90      {
  91          return $this->_subject;
  92      }
  93  
  94      /**
  95       * Remove all prefix text of the subject that matches the subj-leader
  96       * ABNF.
  97       *
  98       * @param string &$str       The subject string.
  99       * @param boolean $keepblob  Remove blob information?
 100       *
 101       * @return boolean  True if string was altered.
 102       */
 103      protected function _removeSubjLeader(&$str, $keepblob = false)
 104      {
 105          $ret = false;
 106  
 107          if (!strlen($str)) {
 108              return $ret;
 109          }
 110  
 111          if ($len = strspn($str, " \t")) {
 112              $str = substr($str, $len);
 113              $ret = true;
 114          }
 115  
 116          $i = 0;
 117  
 118          if (!$keepblob) {
 119              while (isset($str[$i]) && ($str[$i] === '[')) {
 120                  if (($i = $this->_removeBlob($str, $i)) === false) {
 121                      return $ret;
 122                  }
 123              }
 124          }
 125  
 126          if (stripos($str, 're', $i) === 0) {
 127              $i += 2;
 128          } elseif (stripos($str, 'fwd', $i) === 0) {
 129              $i += 3;
 130          } elseif (stripos($str, 'fw', $i) === 0) {
 131              $i += 2;
 132          } else {
 133              return $ret;
 134          }
 135  
 136          $i += strspn($str, " \t", $i);
 137  
 138          if (!$keepblob) {
 139              while (isset($str[$i]) && ($str[$i] === '[')) {
 140                  if (($i = $this->_removeBlob($str, $i)) === false) {
 141                      return $ret;
 142                  }
 143              }
 144          }
 145  
 146          if (!isset($str[$i]) || ($str[$i] !== ':')) {
 147              return $ret;
 148          }
 149  
 150          $str = substr($str, ++$i);
 151  
 152          return true;
 153      }
 154  
 155      /**
 156       * Remove "[...]" text.
 157       *
 158       * @param string $str  The subject string.
 159       * @param integer $i   Current position.
 160       *
 161       * @return boolean|integer  False if blob was not found, otherwise the
 162       *                          string position of the first non-blob char.
 163       */
 164      protected function _removeBlob($str, $i)
 165      {
 166          if ($str[$i] !== '[') {
 167              return false;
 168          }
 169  
 170          ++$i;
 171  
 172          for ($cnt = strlen($str); $i < $cnt; ++$i) {
 173              if ($str[$i] === ']') {
 174                  break;
 175              }
 176  
 177              if ($str[$i] === '[') {
 178                  return false;
 179              }
 180          }
 181  
 182          if ($i === ($cnt - 1)) {
 183              return false;
 184          }
 185  
 186          ++$i;
 187  
 188          if ($str[$i] === ' ') {
 189              ++$i;
 190          }
 191  
 192          return $i;
 193      }
 194  
 195      /**
 196       * Remove "[...]" text if it doesn't result in the subject becoming
 197       * empty.
 198       *
 199       * @param string &$str  The subject string.
 200       *
 201       * @return boolean  True if string was altered.
 202       */
 203      protected function _removeBlobWhenNonempty(&$str)
 204      {
 205          if ($str &&
 206              ($str[0] === '[') &&
 207              (($i = $this->_removeBlob($str, 0)) !== false) &&
 208              ($i !== strlen($str))) {
 209              $str = substr($str, $i);
 210              return true;
 211          }
 212  
 213          return false;
 214      }
 215  
 216      /**
 217       * Remove a "[fwd: ... ]" string.
 218       *
 219       * @param string &$str  The subject string.
 220       *
 221       * @return boolean  True if string was altered.
 222       */
 223      protected function _removeSubjFwdHdr(&$str)
 224      {
 225          if ((stripos($str, '[fwd:') !== 0) || (substr($str, -1) !== ']')) {
 226              return false;
 227          }
 228  
 229          $str = substr($str, 5, -1);
 230          return true;
 231      }
 232  
 233  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1