/framework/Text_Filter/lib/Horde/Text/Filter/Text2html.php

https://github.com/ewandor/horde · PHP · 199 lines · 113 code · 20 blank · 66 comment · 26 complexity · 4a1408c46f300d4bbd1b83c8906a5605 MD5 · raw file

  1. <?php
  2. /**
  3. * Turn text into HTML with varying levels of parsing. For no html
  4. * whatsoever, use htmlspecialchars() instead.
  5. *
  6. * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  7. *
  8. * See the enclosed file COPYING for license information (LGPL). If you
  9. * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  10. *
  11. * @author Chuck Hagenbuch <chuck@horde.org>
  12. * @author Jan Schneider <jan@horde.org>
  13. * @author Michael Slusarz <slusarz@horde.org>
  14. * @category Horde
  15. * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
  16. * @package Text_Filter
  17. */
  18. class Horde_Text_Filter_Text2html extends Horde_Text_Filter_Base
  19. {
  20. const PASSTHRU = 0;
  21. const SYNTAX = 1;
  22. const MICRO = 2;
  23. const MICRO_LINKURL = 3;
  24. const NOHTML = 4;
  25. const NOHTML_NOBREAK = 5;
  26. /**
  27. * Filter parameters.
  28. *
  29. * @var array
  30. */
  31. protected $_params = array(
  32. 'charset' => 'ISO-8859-1',
  33. 'class' => 'fixed',
  34. 'emails' => false,
  35. 'flowed' => '<blockquote>',
  36. 'linkurls' => false,
  37. 'text2html' => false,
  38. 'parselevel' => 0,
  39. 'space2html' => false
  40. );
  41. /**
  42. * Constructor.
  43. *
  44. * @param array $params Parameters specific to this driver:
  45. * <ul>
  46. * <li>charset: (string) The charset to use for htmlspecialchars()
  47. * calls.</li>
  48. * <li>class: (string) See Horde_Text_Filter_Linkurls::.</li>
  49. * <li>emails: (array) TODO</li>
  50. * <li>flowed: (string) For flowed text, the HTML blockquote tag to
  51. * insert before each level.
  52. * <li>linkurls: (array) TODO</li>
  53. * <li>parselevel: (integer) The parselevel of the output.
  54. * <ul>
  55. * <li>PASSTHRU: No action. Pass-through. Included for
  56. * completeness.</li>
  57. * <li>SYNTAX: Allow full html, also do line-breaks, in-lining,
  58. * syntax-parsing.</li>
  59. * <li>MICRO: Micro html (only line-breaks, in-line linking).</li>
  60. * <li>MICRO_LINKURL: Micro html (only line-breaks, in-line linking of
  61. * URLS; no email addresses are linked).</li>
  62. * <li>NOHTML: No html (all stripped, only line-breaks).</li>
  63. * <li>NOHTML_NOBREAK: No html whatsoever, no line breaks added.
  64. * Included for completeness.</li>
  65. * </ul>
  66. * </li>
  67. * <li>space2html: (array) TODO</li>
  68. * </ul>
  69. */
  70. public function __construct($params = array())
  71. {
  72. parent::__construct($params);
  73. // Use ISO-8859-1 instead of US-ASCII
  74. if (Horde_String::lower($this->_params['charset']) == 'us-ascii') {
  75. $this->_params['charset'] = 'iso-8859-1';
  76. }
  77. }
  78. /**
  79. * Executes any code necessary before applying the filter patterns.
  80. *
  81. * @param mixed $text The text before the filtering. Either a string or
  82. * a Horde_Text_Flowed object (since 1.1.0).
  83. *
  84. * @return string The modified text.
  85. */
  86. public function preProcess($text)
  87. {
  88. if ($text instanceof Horde_Text_Flowed) {
  89. $text->setMaxLength(0);
  90. $lines = $text->toFixedArray();
  91. $level = 0;
  92. $out = $txt = '';
  93. foreach ($lines as $key => $val) {
  94. $line = ltrim($val['text'], '>');
  95. if (!isset($lines[$key + 1])) {
  96. $out .= $this->preProcess(ltrim($txt) . $line);
  97. while (--$level > 0) {
  98. $out .= '</blockquote>';
  99. }
  100. } elseif ($val['level'] > $level) {
  101. $out .= $this->preProcess(ltrim($txt));
  102. do {
  103. $out .= $this->_params['flowed'];
  104. } while (++$level != $val['level']);
  105. $txt = $line;
  106. } elseif ($val['level'] < $level) {
  107. $out .= $this->preProcess(ltrim($txt));
  108. do {
  109. $out .= '</blockquote>';
  110. } while (--$level != $val['level']);
  111. $txt = $line;
  112. } else {
  113. $txt .= "\n" . $line;
  114. }
  115. }
  116. return $out;
  117. }
  118. if (!strlen($text)) {
  119. return '';
  120. }
  121. /* Abort out on simple cases. */
  122. if ($this->_params['parselevel'] == self::PASSTHRU) {
  123. return $text;
  124. }
  125. if ($this->_params['parselevel'] == self::NOHTML_NOBREAK) {
  126. return @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
  127. }
  128. if ($this->_params['parselevel'] < self::NOHTML) {
  129. $filters = array();
  130. if ($this->_params['linkurls']) {
  131. reset($this->_params['linkurls']);
  132. $this->_params['linkurls'][key($this->_params['linkurls'])]['encode'] = true;
  133. $filters = $this->_params['linkurls'];
  134. } else {
  135. $filters['linkurls'] = array(
  136. 'encode' => true
  137. );
  138. }
  139. if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
  140. if ($this->_params['emails']) {
  141. reset($this->_params['emails']);
  142. $this->_params['emails'][key($this->_params['emails'])]['encode'] = true;
  143. $filters += $this->_params['emails'];
  144. } else {
  145. $filters['emails'] = array(
  146. 'encode' => true
  147. );
  148. }
  149. }
  150. $text = Horde_Text_Filter::filter($text, array_keys($filters), array_values($filters));
  151. }
  152. /* For level MICRO or NOHTML, start with htmlspecialchars(). */
  153. $text2 = @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
  154. /* Bad charset input in may result in an empty string. If so, try
  155. * using the default charset encoding instead. */
  156. if (!$text2) {
  157. $text2 = @htmlspecialchars($text, ENT_COMPAT);
  158. }
  159. $text = $text2;
  160. /* Do in-lining of http://xxx.xxx to link, xxx@xxx.xxx to email. */
  161. if ($this->_params['parselevel'] < self::NOHTML) {
  162. $text = Horde_Text_Filter_Linkurls::decode($text);
  163. if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
  164. $text = Horde_Text_Filter_Emails::decode($text);
  165. }
  166. if ($this->_params['space2html']) {
  167. $params = reset($this->_params['space2html']);
  168. $driver = key($this->_params['space2html']);
  169. } else {
  170. $driver = 'space2html';
  171. $params = array();
  172. }
  173. $text = Horde_Text_Filter::filter($text, $driver, $params);
  174. }
  175. /* Do the newline ---> <br /> substitution. Everybody gets this; if
  176. * you don't want even that, just use htmlspecialchars(). */
  177. return nl2br($text);
  178. }
  179. }