Пример #1
0
 /**
  * Reformats the input string, where the string is 'format=flowed' plain
  * text as described in RFC 2646.
  *
  * @param boolean $toflowed  Convert to flowed?
  * @param boolean $quote     Add level of quoting to each line?
  * @param boolean $wrap      Wrap unquoted lines?
  */
 protected function _reformat($toflowed, $quote, $wrap = true)
 {
     $format_type = implode('|', array($toflowed, $quote));
     if ($format_type == $this->_formattype) {
         return;
     }
     $this->_output = array();
     $this->_formattype = $format_type;
     /* Set variables used in regexps. */
     $delsp = $toflowed && $this->_delsp ? 1 : 0;
     $opt = $this->_optlength - 1 - $delsp;
     /* Process message line by line. */
     $text = preg_split("/\r?\n/", $this->_text);
     $text_count = count($text) - 1;
     $skip = 0;
     reset($text);
     while (list($no, $line) = each($text)) {
         if ($skip) {
             --$skip;
             continue;
         }
         /* Per RFC 2646 [4.3], the 'Usenet Signature Convention' line
          * (DASH DASH SP) is not considered flowed.  Watch for this when
          * dealing with potentially flowed lines. */
         /* The next three steps come from RFC 2646 [4.2]. */
         /* STEP 1: Determine quote level for line. */
         if ($num_quotes = $this->_numquotes($line)) {
             $line = substr($line, $num_quotes);
         }
         /* Only combine lines if we are converting to flowed or if the
          * current line is quoted. */
         if (!$toflowed || $num_quotes) {
             /* STEP 2: Remove space stuffing from line. */
             $line = $this->_unstuff($line);
             /* STEP 3: Should we interpret this line as flowed?
              * While line is flowed (not empty and there is a space
              * at the end of the line), and there is a next line, and the
              * next line has the same quote depth, add to the current
              * line. A line is not flowed if it is a signature line. */
             if ($line != '-- ') {
                 while (!empty($line) && substr($line, -1) == ' ' && $text_count != $no && $this->_numquotes($text[$no + 1]) == $num_quotes) {
                     /* If DelSp is yes and this is flowed input, we need to
                      * remove the trailing space. */
                     if (!$toflowed && $this->_delsp) {
                         $line = substr($line, 0, -1);
                     }
                     $line .= $this->_unstuff(substr($text[++$no], $num_quotes));
                     ++$skip;
                 }
             }
         }
         /* Ensure line is fixed, since we already joined all flowed
          * lines. Remove all trailing ' ' from the line. */
         if ($line != '-- ') {
             $line = rtrim($line);
         }
         /* Increment quote depth if we're quoting. */
         if ($quote) {
             $num_quotes++;
         }
         /* The quote prefix for the line. */
         $quotestr = str_repeat('>', $num_quotes);
         if (empty($line)) {
             /* Line is empty. */
             $this->_output[] = array('text' => $quotestr, 'level' => $num_quotes);
         } elseif (!$wrap && !$num_quotes || empty($this->_maxlength) || Horde_String::length($line, $this->_charset) + $num_quotes <= $this->_maxlength) {
             /* Line does not require rewrapping. */
             $this->_output[] = array('text' => $quotestr . $this->_stuff($line, $num_quotes, $toflowed), 'level' => $num_quotes);
         } else {
             $min = $num_quotes + 1;
             /* Rewrap this paragraph. */
             while ($line) {
                 /* Stuff and re-quote the line. */
                 $line = $quotestr . $this->_stuff($line, $num_quotes, $toflowed);
                 $line_length = Horde_String::length($line, $this->_charset);
                 if ($line_length <= $this->_optlength) {
                     /* Remaining section of line is short enough. */
                     $this->_output[] = array('text' => $line, 'level' => $num_quotes);
                     break;
                 } else {
                     $regex = array();
                     if ($min <= $opt) {
                         $regex[] = '^(.{' . $min . ',' . $opt . '}) (.*)';
                     }
                     if ($min <= $this->_maxlength) {
                         $regex[] = '^(.{' . $min . ',' . $this->_maxlength . '}) (.*)';
                     }
                     $regex[] = '^(.{' . $min . ',})? (.*)';
                     if ($m = Horde_String::regexMatch($line, $regex, $this->_charset)) {
                         /* We need to wrap text at a certain number of
                          * *characters*, not a certain number of *bytes*;
                          * thus the need for a multibyte capable regex.
                          * If a multibyte regex isn't available, we are
                          * stuck with preg_match() (the function will
                          * still work - are just left with shorter rows
                          * than expected if multibyte characters exist in
                          * the row).
                          *
                          * 1. Try to find a string as long as _optlength.
                          * 2. Try to find a string as long as _maxlength.
                          * 3. Take the first word. */
                         if (empty($m[1])) {
                             $m[1] = $m[2];
                             $m[2] = '';
                         }
                         $this->_output[] = array('text' => $m[1] . ' ' . ($delsp ? ' ' : ''), 'level' => $num_quotes);
                         $line = $m[2];
                     } elseif ($line_length > 998) {
                         /* One excessively long word left on line.  Be
                          * absolutely sure it does not exceed 998
                          * characters in length or else we must
                          * truncate. */
                         $this->_output[] = array('text' => Horde_String::substr($line, 0, 998, $this->_charset), 'level' => $num_quotes);
                         $line = Horde_String::substr($line, 998, null, $this->_charset);
                     } else {
                         $this->_output[] = array('text' => $line, 'level' => $num_quotes);
                         break;
                     }
                 }
             }
         }
     }
 }