PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/program/include/rcube_string_replacer.php

https://github.com/netconstructor/roundcubemail
PHP | 195 lines | 98 code | 23 blank | 74 comment | 14 complexity | b2e5b649fa0fd072000455812922724e MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1
  1. <?php
  2. /*
  3. +-----------------------------------------------------------------------+
  4. | program/include/rcube_string_replacer.php |
  5. | |
  6. | This file is part of the Roundcube Webmail client |
  7. | Copyright (C) 2009, The Roundcube Dev Team |
  8. | |
  9. | Licensed under the GNU General Public License version 3 or |
  10. | any later version with exceptions for skins & plugins. |
  11. | See the README file for a full license statement. |
  12. | |
  13. | PURPOSE: |
  14. | Handle string replacements based on preg_replace_callback |
  15. | |
  16. +-----------------------------------------------------------------------+
  17. | Author: Thomas Bruederli <roundcube@gmail.com> |
  18. +-----------------------------------------------------------------------+
  19. */
  20. /**
  21. * Helper class for string replacements based on preg_replace_callback
  22. *
  23. * @package Framework
  24. * @subpackage Utils
  25. */
  26. class rcube_string_replacer
  27. {
  28. public static $pattern = '/##str_replacement\[([0-9]+)\]##/';
  29. public $mailto_pattern;
  30. public $link_pattern;
  31. private $values = array();
  32. function __construct()
  33. {
  34. // Simplified domain expression for UTF8 characters handling
  35. // Support unicode/punycode in top-level domain part
  36. $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.?([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-zA-Z0-9]{2,})';
  37. $url1 = '.:;,';
  38. $url2 = 'a-zA-Z0-9%=#$@+?!&\\/_~\\[\\]{}\*-';
  39. $this->link_pattern = "/([\w]+:\/\/|\W[Ww][Ww][Ww]\.|^[Ww][Ww][Ww]\.)($utf_domain([$url1]?[$url2]+)*)/";
  40. $this->mailto_pattern = "/("
  41. ."[-\w!\#\$%&\'*+~\/^`|{}=]+(?:\.[-\w!\#\$%&\'*+~\/^`|{}=]+)*" // local-part
  42. ."@$utf_domain" // domain-part
  43. ."(\?[$url1$url2]+)?" // e.g. ?subject=test...
  44. .")/";
  45. }
  46. /**
  47. * Add a string to the internal list
  48. *
  49. * @param string String value
  50. * @return int Index of value for retrieval
  51. */
  52. public function add($str)
  53. {
  54. $i = count($this->values);
  55. $this->values[$i] = $str;
  56. return $i;
  57. }
  58. /**
  59. * Build replacement string
  60. */
  61. public function get_replacement($i)
  62. {
  63. return '##str_replacement['.$i.']##';
  64. }
  65. /**
  66. * Callback function used to build HTML links around URL strings
  67. *
  68. * @param array Matches result from preg_replace_callback
  69. * @return int Index of saved string value
  70. */
  71. public function link_callback($matches)
  72. {
  73. $i = -1;
  74. $scheme = strtolower($matches[1]);
  75. if (preg_match('!^(http|ftp|file)s?://!i', $scheme)) {
  76. $url = $matches[1] . $matches[2];
  77. }
  78. else if (preg_match('/^(\W*)(www\.)$/i', $matches[1], $m)) {
  79. $url = $m[2] . $matches[2];
  80. $url_prefix = 'http://';
  81. $prefix = $m[1];
  82. }
  83. if ($url) {
  84. $suffix = $this->parse_url_brackets($url);
  85. $i = $this->add($prefix . html::a(array(
  86. 'href' => $url_prefix . $url,
  87. 'target' => '_blank'
  88. ), rcmail::Q($url)) . $suffix);
  89. }
  90. // Return valid link for recognized schemes, otherwise, return the unmodified string for unrecognized schemes.
  91. return $i >= 0 ? $this->get_replacement($i) : $matches[0];
  92. }
  93. /**
  94. * Callback function used to build mailto: links around e-mail strings
  95. *
  96. * @param array Matches result from preg_replace_callback
  97. * @return int Index of saved string value
  98. */
  99. public function mailto_callback($matches)
  100. {
  101. $href = $matches[1];
  102. $suffix = $this->parse_url_brackets($href);
  103. $i = $this->add(html::a(array(
  104. 'href' => 'mailto:' . $href,
  105. 'onclick' => "return ".rcmail::JS_OBJECT_NAME.".command('compose','".rcmail::JQ($href)."',this)",
  106. ), rcmail::Q($href)) . $suffix);
  107. return $i >= 0 ? $this->get_replacement($i) : '';
  108. }
  109. /**
  110. * Look up the index from the preg_replace matches array
  111. * and return the substitution value.
  112. *
  113. * @param array Matches result from preg_replace_callback
  114. * @return string Value at index $matches[1]
  115. */
  116. public function replace_callback($matches)
  117. {
  118. return $this->values[$matches[1]];
  119. }
  120. /**
  121. * Replace all defined (link|mailto) patterns with replacement string
  122. *
  123. * @param string $str Text
  124. *
  125. * @return string Text
  126. */
  127. public function replace($str)
  128. {
  129. // search for patterns like links and e-mail addresses
  130. $str = preg_replace_callback($this->link_pattern, array($this, 'link_callback'), $str);
  131. $str = preg_replace_callback($this->mailto_pattern, array($this, 'mailto_callback'), $str);
  132. return $str;
  133. }
  134. /**
  135. * Replace substituted strings with original values
  136. */
  137. public function resolve($str)
  138. {
  139. return preg_replace_callback(self::$pattern, array($this, 'replace_callback'), $str);
  140. }
  141. /**
  142. * Fixes bracket characters in URL handling
  143. */
  144. public static function parse_url_brackets(&$url)
  145. {
  146. // #1487672: special handling of square brackets,
  147. // URL regexp allows [] characters in URL, for example:
  148. // "http://example.com/?a[b]=c". However we need to handle
  149. // properly situation when a bracket is placed at the end
  150. // of the link e.g. "[http://example.com]"
  151. if (preg_match('/(\\[|\\])/', $url)) {
  152. $in = false;
  153. for ($i=0, $len=strlen($url); $i<$len; $i++) {
  154. if ($url[$i] == '[') {
  155. if ($in)
  156. break;
  157. $in = true;
  158. }
  159. else if ($url[$i] == ']') {
  160. if (!$in)
  161. break;
  162. $in = false;
  163. }
  164. }
  165. if ($i<$len) {
  166. $suffix = substr($url, $i);
  167. $url = substr($url, 0, $i);
  168. }
  169. }
  170. return $suffix;
  171. }
  172. }