[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/Text/ -> Flowed.php (source)

   1  <?php
   2  /**
   3   * The Text_Flowed:: class provides common methods for manipulating text
   4   * using the encoding described in RFC 3676 ('flowed' text).
   5   *
   6   * $Horde: framework/Text_Flowed/Flowed.php,v 1.14.10.17 2006/03/11 09:50:22 jan Exp $
   7   *
   8   * This class is based on the Text::Flowed perl module (Version 0.14) found
   9   * in the CPAN perl repository.  This module is released under the Perl
  10   * license, which is compatible with the LGPL.
  11   *
  12   * Copyright 2002-2003 Philip Mak
  13   * Copyright 2004-2006 Michael Slusarz <slusarz@bigworm.colorado.edu>
  14   *
  15   * See the enclosed file COPYING for license information (LGPL). If you
  16   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  17   *
  18   * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
  19   * @since   Horde 3.0
  20   * @package Horde_Text
  21   */
  22  class Text_Flowed {
  23  
  24      /**
  25       * The maximum length that a line is allowed to be (unless faced with
  26       * with a word that is unreasonably long). This class will re-wrap a
  27       * line if it exceeds this length.
  28       *
  29       * @var integer
  30       */
  31      var $_maxlength = 78;
  32  
  33      /**
  34       * When this class wraps a line, the newly created lines will be split
  35       * at this length.
  36       *
  37       * @var integer
  38       */
  39      var $_optlength = 72;
  40  
  41      /**
  42       * The text to be formatted.
  43       *
  44       * @var string
  45       */
  46      var $_text;
  47  
  48      /**
  49       * The cached output of the formatting.
  50       *
  51       * @var array
  52       */
  53      var $_output = null;
  54  
  55      /**
  56       * The character set of the text.
  57       *
  58       * @var string
  59       */
  60      var $_charset;
  61  
  62      /**
  63       * Convert text using DelSp?
  64       *
  65       * @var boolean
  66       */
  67      var $_delsp = false;
  68  
  69      /**
  70       * Constructor.
  71       *
  72       * @param string $text     The text to process.
  73       * @param string $charset  The character set of $text.
  74       */
  75      function Text_Flowed($text, $charset = null)
  76      {
  77          $this->_text = $text;
  78          $this->_charset = $charset;
  79      }
  80  
  81      /**
  82       * Set the maximum length of a line of text.
  83       *
  84       * @param integer $max  A new value for $_maxlength.
  85       */
  86      function setMaxLength($max)
  87      {
  88          $this->_maxlength = $max;
  89      }
  90  
  91      /**
  92       * Set the optimal length of a line of text.
  93       *
  94       * @param integer $max  A new value for $_optlength.
  95       */
  96      function setOptLength($opt)
  97      {
  98          $this->_optlength = $opt;
  99      }
 100  
 101      /**
 102       * Set whether to format test using DelSp.
 103       *
 104       * @since Horde 3.1
 105       *
 106       * @param boolean $delsp  Use DelSp?
 107       */
 108      function setDelSp($delsp)
 109      {
 110          $this->_delsp = (bool) $delsp;
 111      }
 112  
 113      /**
 114       * Reformats the input string, where the string is 'format=flowed' plain
 115       * text as described in RFC 2646.
 116       *
 117       * @param boolean $quote  Add level of quoting to each line?
 118       *
 119       * @return string  The text converted to RFC 2646 'fixed' format.
 120       */
 121      function toFixed($quote = false)
 122      {
 123          $txt = '';
 124  
 125          $this->_reformat(false, $quote);
 126          foreach ($this->_output as $val) {
 127              $txt .= $val['text'] . "\n";
 128          }
 129          return rtrim($txt);
 130      }
 131  
 132      /**
 133       * Reformats the input string, and returns the output in an array format
 134       * with quote level information.
 135       *
 136       * @param boolean $quote  Add level of quoting to each line?
 137       *
 138       * @return array  An array of arrays with the following elements:
 139       * <pre>
 140       * 'level' - The quote level of the current line.
 141       * 'text'  - The text for the current line.
 142       * </pre>
 143       */
 144      function toFixedArray($quote = false)
 145      {
 146          $this->_reformat(false, $quote);
 147          return $this->_output;
 148      }
 149  
 150      /**
 151       * Reformats the input string, where the string is 'format=fixed' plain
 152       * text as described in RFC 2646.
 153       *
 154       * @param boolean $quote  Add level of quoting to each line?
 155       *
 156       * @return string  The text converted to RFC 2646 'flowed' format.
 157       */
 158      function toFlowed($quote = false)
 159      {
 160          $txt = '';
 161  
 162          $this->_reformat(true, $quote);
 163          foreach ($this->_output as $val) {
 164              $txt .= $val['text'] . "\n";
 165          }
 166          return $txt;
 167      }
 168  
 169      /**
 170       * Reformats the input string, where the string is 'format=flowed' plain
 171       * text as described in RFC 2646.
 172       *
 173       * @access private
 174       *
 175       * @param boolean $toflowed  Convert to flowed?
 176       * @param boolean $quote     Add level of quoting to each line?
 177       *
 178       * @return array  A list of arrays.
 179       */
 180      function _reformat($toflowed, $quote)
 181      {
 182          if (!is_null($this->_output)) {
 183              return;
 184          }
 185  
 186          $this->_output = array();
 187          $text = explode("\n", $this->_text);
 188  
 189          /* Set variables used in regexps. */
 190          $delsp = ($toflowed && $this->_delsp) ? 1 : 0;
 191          $opt = $this->_optlength - 1 - $delsp;
 192  
 193          /* Process message line by line. */
 194          do {
 195              $line = array_shift($text);
 196  
 197              /* Per RFC 2646 [4.3], the 'Usenet Signature Convention' line
 198               * (DASH DASH SP) is not considered flowed.  Watch for this when
 199               * dealing with potentially flowed lines. */
 200  
 201              /* The next three steps come from RFC 2646 [4.2]. */
 202              /* STEP 1: Determine quote level for line. */
 203              if (($num_quotes = $this->_numquotes($line))) {
 204                  $line = substr($line, $num_quotes);
 205              }
 206  
 207              /* Only combine lines if we are converting to flowed or if the
 208               * current line is quoted. */
 209              if (!$toflowed || $num_quotes) {
 210                  /* STEP 2: Remove space stuffing from line. */
 211                  $line = $this->_unstuff($line);
 212  
 213                  /* STEP 3: Should we interpret this line as flowed?
 214                   * While line is flowed (not empty and there is a space
 215                   * at the end of the line), and there is a next line, and the
 216                   * next line has the same quote depth, add to the current
 217                   * line. A line is not flowed if it is a signature line. */
 218                  while (!empty($line) &&
 219                         ($line != '-- ') &&
 220                         ($line{strlen($line)-1} == ' ') &&
 221                         !empty($text) &&
 222                         ($this->_numquotes($text[0]) == $num_quotes)) {
 223                      /* If DelSp is yes and this is flowed input, we need to
 224                       * remove the trailing space. */
 225                      if (!$toflowed && $this->_delsp) {
 226                          $line = substr($line, 0, -1);
 227                      }
 228                      $line .= $this->_unstuff(substr(array_shift($text), $num_quotes));
 229                  }
 230              }
 231  
 232              /* Ensure line is fixed, since we already joined all flowed
 233               * lines. Remove all trailing ' ' from the line. */
 234              if ($line != '-- ') {
 235                  $line = rtrim($line);
 236              }
 237  
 238              /* Increment quote depth if we're quoting. */
 239              if ($quote) {
 240                  $num_quotes++;
 241              }
 242  
 243              /* The quote prefix for the line. */
 244              $quotestr = str_repeat('>', $num_quotes);
 245  
 246              if (empty($line)) {
 247                  /* Line is empty. */
 248                  $this->_output[] = array('text' => $quotestr, 'level' => $num_quotes);
 249              } elseif (empty($this->_maxlength) || ((String::length($line, $this->_charset) + $num_quotes) <= $this->_maxlength)) {
 250                  /* Line does not require rewrapping. */
 251                  $this->_output[] = array('text' => $quotestr . $this->_stuff($line, $num_quotes, $toflowed), 'level' => $num_quotes);
 252              } else {
 253                  $min = $num_quotes + 1;
 254  
 255                  /* Rewrap this paragraph. */
 256                  while ($line) {
 257                      /* Stuff and re-quote the line. */
 258                      $line = $quotestr . $this->_stuff($line, $num_quotes, $toflowed);
 259                      $line_length = String::length($line, $this->_charset);
 260                      if ($line_length <= $this->_optlength) {
 261                          /* Remaining section of line is short enough. */
 262                          $this->_output[] = array('text' => $line, 'level' => $num_quotes);
 263                          break;
 264                      } elseif ($m = String::regexMatch($line, array('^(.{' . $min . ',' . $opt . '}) (.*)', '^(.{' . $min . ',' . $this->_maxlength . '}) (.*)', '^(.{' . $min . ',})? (.*)'), $this->_charset)) {
 265                          /* We need to wrap text at a certain number of
 266                           * *characters*, not a certain number of *bytes*;
 267                           * thus the need for a multibyte capable regex.
 268                           * If a multibyte regex isn't available, we are stuck
 269                           * with preg_match() (the function will still work -
 270                           * we will just be left with shorter rows than expected
 271                           * if multibyte characters exist in the row).
 272                           *
 273                           * Algorithim:
 274                           * 1. Try to find a string as long as _optlength.
 275                           * 2. Try to find a string as long as _maxlength.
 276                           * 3. Take the first word. */
 277                          if (empty($m[1])) {
 278                              $m[1] = $m[2];
 279                              $m[2] = '';
 280                          }
 281                          $this->_output[] = array('text' => $m[1] . ' ' . (($delsp) ? ' ' : ''), 'level' => $num_quotes);
 282                          $line = $m[2];
 283                      } else {
 284                          /* One excessively long word left on line.  Be
 285                           * absolutely sure it does not exceed 998 characters
 286                           * in length or else we must truncate. */
 287                          if ($line_length > 998) { 
 288                              $this->_output[] = array('text' => String::substr($line, 0, 998, $this->_charset), 'level' => $num_quotes);
 289                              $line = String::substr($line, 998, null, $this->_charset);
 290                          } else {
 291                              $this->_output[] = array('text' => $line, 'level' => $num_quotes);
 292                              break;
 293                          }
 294                      }
 295                  }
 296              }
 297          } while (!empty($text));
 298      }
 299  
 300      /**
 301       * Returns the number of leading '>' characters in the text input.
 302       * '>' characters are defined by RFC 2646 to indicate a quoted line.
 303       *
 304       * @access private
 305       *
 306       * @param string $text  The text to analyze.
 307       *
 308       * @return integer  The number of leading quote characters.
 309       */
 310      function _numquotes($text)
 311      {
 312          return strspn($text, '>');
 313      }
 314  
 315      /**
 316       * Space-stuffs if it starts with ' ' or '>' or 'From ', or if
 317       * quote depth is non-zero (for aesthetic reasons so that there is a
 318       * space after the '>').
 319       *
 320       * @access private
 321       *
 322       * @param string $text        The text to stuff.
 323       * @param string $num_quotes  The quote-level of this line.
 324       * @param boolean $toflowed   Are we converting to flowed text?
 325       *
 326       * @return string  The stuffed text.
 327       */
 328      function _stuff($text, $num_quotes, $toflowed)
 329      {
 330          if ($toflowed &&
 331              ($num_quotes || preg_match("/^(?: |>|From |From$)/", $text))) {
 332              return ' ' . $text;
 333          }
 334          return $text;
 335      }
 336  
 337      /**
 338       * Unstuffs a space stuffed line.
 339       *
 340       * @access private
 341       *
 342       * @param string $text  The text to unstuff.
 343       *
 344       * @return string  The unstuffed text.
 345       */
 346      function _unstuff($text)
 347      {
 348          if (!empty($text) && ($text{0} == ' ')) {
 349              $text = substr($text, 1);
 350          }
 351          return $text;
 352      }
 353  
 354  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7