From aa055c931a68547763f7bb89425a08e8ceecb749 Mon Sep 17 00:00:00 2001 From: thomascube Date: Thu, 22 Jan 2009 14:47:23 +0000 Subject: Get rid of vulnerable preg_replace eval and create_function (#1485686) + correctly handle base and link tags in html messages --- program/include/rcube_string_replacer.php | 116 ++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 program/include/rcube_string_replacer.php (limited to 'program/include/rcube_string_replacer.php') diff --git a/program/include/rcube_string_replacer.php b/program/include/rcube_string_replacer.php new file mode 100644 index 000000000..fe082a583 --- /dev/null +++ b/program/include/rcube_string_replacer.php @@ -0,0 +1,116 @@ + | + +-----------------------------------------------------------------------+ + + $Id: $ + +*/ + + +/** + * Helper class for string replacements based on preg_replace_callback + * + * @package Core + */ +class rcube_string_replacer +{ + public static $pattern = '/##str_replacement\[([0-9]+)\]##/'; + + private $values = array(); + + + /** + * Add a string to the internal list + * + * @param string String value + * @return int Index of value for retrieval + */ + public function add($str) + { + $i = count($this->values); + $this->values[$i] = $str; + return $i; + } + + /** + * Build replacement string + */ + public function get_replacement($i) + { + return '##str_replacement['.$i.']##'; + } + + /** + * Callback function used to build HTML links around URL strings + * + * @param array Matches result from preg_replace_callback + * @return int Index of saved string value + */ + public function link_callback($matches) + { + $i = -1; + $scheme = strtolower($matches[1]); + + if ($scheme == 'http' || $scheme == 'https' || $scheme == 'ftp') { + $url = $matches[1] . '://' . $matches[2]; + $i = $this->add(html::a(array('href' => $url, 'target' => "_blank"), Q($url))); + } + else if ($matches[2] == 'www.') { + $url = $matches[2] . $matches[3]; + $i = $this->add($matches[1] . html::a(array('href' => 'http://' . $url, 'target' => "_blank"), Q($url))); + } + + return $i >= 0 ? $this->get_replacement($i) : ''; + } + + /** + * Callback function used to build mailto: links around e-mail strings + * + * @param array Matches result from preg_replace_callback + * @return int Index of saved string value + */ + public function mailto_callback($matches) + { + $i = $this->add(html::a(array( + 'href' => 'mailto:' . $matches[1], + 'onclick' => "return ".JS_OBJECT_NAME.".command('compose','".JQ($matches[1])."',this)", + ), + Q($matches[1]))); + + return $i >= 0 ? $this->get_replacement($i) : ''; + } + + /** + * Look up the index from the preg_replace matches array + * and return the substitution value. + * + * @param array Matches result from preg_replace_callback + * @return string Value at index $matches[1] + */ + public function replace_callback($matches) + { + return $this->values[$matches[1]]; + } + + /** + * Replace substituted strings with original values + */ + public function resolve($str) + { + return preg_replace_callback(self::$pattern, array($this, 'replace_callback'), $str); + } + +} \ No newline at end of file -- cgit v1.2.3