PageRenderTime 67ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/public/wp-content/plugins/wp-multibyte-patch/wp-multibyte-patch.php

http://wpzf.googlecode.com/
PHP | 443 lines | 398 code | 30 blank | 15 comment | 15 complexity | c44c9debdcb3c1c0060bcb7aa001587a MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.1
  1. <?php
  2. /*
  3. Plugin Name: WP Multibyte Patch
  4. Plugin URI: http://eastcoder.com/code/wp-multibyte-patch/
  5. Description: Enhances multibyte string I/O functionality of WordPress.
  6. Author: Kuraishi (tenpura)
  7. Version: 1.5
  8. Author URI: http://eastcoder.com/
  9. Text Domain: wp-multibyte-patch
  10. Domain Path: /languages
  11. */
  12. /*
  13. Copyright (C) 2011 Kuraishi (Email: 210pura at gmail dot com), Tinybit Inc.
  14. This program is licensed under the GNU GPL Version 2.
  15. */
  16. class multibyte_patch {
  17. // Do not edit this section. Use wpmp-config.php instead.
  18. var $conf = array(
  19. 'excerpt_length' => 55,
  20. 'excerpt_mblength' => 110,
  21. 'excerpt_more' => ' [...]',
  22. 'comment_excerpt_length' => 20,
  23. 'comment_excerpt_mblength' => 40,
  24. 'ascii_threshold' => 90,
  25. 'patch_wp_mail' => true,
  26. 'patch_incoming_trackback' => true,
  27. 'patch_incoming_pingback' => true,
  28. 'patch_wp_trim_excerpt' => true,
  29. 'patch_get_comment_excerpt' => true,
  30. 'patch_process_search_terms' => true,
  31. 'patch_admin_custom_css' => true,
  32. 'patch_wplink_js' => true,
  33. 'patch_word_count_js' => true,
  34. 'patch_sanitize_file_name' => true,
  35. 'patch_bp_create_excerpt' => false,
  36. 'bp_excerpt_mblength' => 110,
  37. 'bp_excerpt_more' => ' [...]'
  38. );
  39. var $blog_encoding;
  40. var $has_mbfunctions;
  41. var $textdomain = 'wp-multibyte-patch';
  42. var $lang_dir = 'languages';
  43. var $required_version = '3.2';
  44. var $query_based_vars = array();
  45. function guess_encoding($string, $encoding = '') {
  46. $blog_encoding = $this->blog_encoding;
  47. if(!$encoding && seems_utf8($string))
  48. return 'UTF-8';
  49. elseif(!$encoding)
  50. return $blog_encoding;
  51. else
  52. return $encoding;
  53. }
  54. function convenc($string, $to_encoding, $from_encoding = '') {
  55. $blog_encoding = $this->blog_encoding;
  56. if('' == $from_encoding)
  57. $from_encoding = $blog_encoding;
  58. if(strtoupper($to_encoding) == strtoupper($from_encoding))
  59. return $string;
  60. else
  61. return mb_convert_encoding($string, $to_encoding, $from_encoding);
  62. }
  63. function incoming_trackback($commentdata) {
  64. global $wpdb;
  65. if('trackback' != $commentdata['comment_type'])
  66. return $commentdata;
  67. if(false === $this->conf['patch_incoming_trackback'])
  68. return $commentdata;
  69. $title = isset($_POST['title']) ? stripslashes($_POST['title']) : '';
  70. $excerpt = isset($_POST['excerpt']) ? stripslashes($_POST['excerpt']) : '';
  71. $blog_name = isset($_POST['blog_name']) ? stripslashes($_POST['blog_name']) : '';
  72. $blog_encoding = $this->blog_encoding;
  73. $from_encoding = isset($_POST['charset']) ? $_POST['charset'] : '';
  74. if(!$from_encoding)
  75. $from_encoding = (preg_match("/^.*charset=([a-zA-Z0-9\-_]+).*$/i", $_SERVER['CONTENT_TYPE'], $matched)) ? $matched[1] : '';
  76. $from_encoding = str_replace(array(',', ' '), '', strtoupper(trim($from_encoding)));
  77. $from_encoding = $this->guess_encoding($excerpt . $title . $blog_name, $from_encoding);
  78. $title = $this->convenc($title, $blog_encoding, $from_encoding);
  79. $blog_name = $this->convenc($blog_name, $blog_encoding, $from_encoding);
  80. $excerpt = $this->convenc($excerpt, $blog_encoding, $from_encoding);
  81. $title = strip_tags($title);
  82. $excerpt = strip_tags($excerpt);
  83. $title = (strlen($title) > 250) ? mb_strcut($title, 0, 250, $blog_encoding) . '...' : $title;
  84. $excerpt = (strlen($excerpt) > 255) ? mb_strcut($excerpt, 0, 252, $blog_encoding) . '...' : $excerpt;
  85. $commentdata['comment_author'] = $wpdb->escape($blog_name);
  86. $commentdata['comment_content'] = $wpdb->escape("<strong>$title</strong>\n\n$excerpt");
  87. return $commentdata;
  88. }
  89. function pre_remote_source($linea, $pagelinkedto) {
  90. $this->pingback_ping_linea = $linea;
  91. $this->pingback_ping_pagelinkedto = $pagelinkedto;
  92. return $linea;
  93. }
  94. function incoming_pingback($commentdata) {
  95. if('pingback' != $commentdata['comment_type'])
  96. return $commentdata;
  97. if(false === $this->conf['patch_incoming_pingback'])
  98. return $commentdata;
  99. $pagelinkedto = $this->pingback_ping_pagelinkedto;
  100. $linea = $this->pingback_ping_linea;
  101. $linea = preg_replace("/" . preg_quote('<!DOC', '/') . "/i", '<DOC', $linea);
  102. $linea = preg_replace("/[\r\n\t ]+/", ' ', $linea);
  103. $linea = preg_replace("/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/i", "\n\n", $linea);
  104. preg_match("/<meta[^<>]+charset=\"*([a-zA-Z0-9\-_]+)\"*[^<>]*>/i", $linea, $matches);
  105. $charset = isset($matches[1]) ? $matches[1] : '';
  106. $from_encoding = $this->guess_encoding(strip_tags($linea), $charset);
  107. $blog_encoding = $this->blog_encoding;
  108. $linea = strip_tags($linea, '<a>');
  109. $linea = $this->convenc($linea, $blog_encoding, $from_encoding);
  110. $p = explode("\n\n", $linea);
  111. foreach ($p as $para) {
  112. if(strpos($para, $pagelinkedto) !== false && preg_match("/^([^<>]*)(\<a[^<>]+[\"']" . preg_quote($pagelinkedto, '/') . "[\"'][^<>]*\>)([^<>]+)(\<\/a\>)(.*)$/i", $para, $context))
  113. break;
  114. }
  115. if(!$context)
  116. return $commentdata;
  117. $context[1] = strip_tags($context[1]);
  118. $context[5] = strip_tags($context[5]);
  119. $len_max = 250;
  120. $len_c3 = strlen($context[3]);
  121. if($len_c3 > $len_max) {
  122. $excerpt = mb_strcut($context[3], 0, 250, $blog_encoding);
  123. } else {
  124. $len_c1 = strlen($context[1]);
  125. $len_c5 = strlen($context[5]);
  126. $len_left = $len_max - $len_c3;
  127. $len_left_even = ceil($len_left / 2);
  128. if($len_left_even > $len_c1) {
  129. $context[5] = mb_strcut($context[5], 0, $len_left - $len_c1, $blog_encoding);
  130. }
  131. elseif($len_left_even > $len_c5) {
  132. $context[1] .= "\t\t\t\t\t\t";
  133. $context[1] = mb_strcut($context[1], $len_c1 - ($len_left - $len_c5), $len_c1 + 6, $blog_encoding);
  134. $context[1] = preg_replace("/\t*$/", '', $context[1]);
  135. }
  136. else {
  137. $context[1] .= "\t\t\t\t\t\t";
  138. $context[1] = mb_strcut($context[1], $len_c1 - $len_left_even, $len_c1 + 6, $blog_encoding);
  139. $context[1] = preg_replace("/\t*$/", '', $context[1]);
  140. $context[5] = mb_strcut($context[5], 0, $len_left_even, $blog_encoding);
  141. }
  142. $excerpt = $context[1] . $context[3] . $context[5];
  143. }
  144. $commentdata['comment_content'] = '[...] ' . esc_html($excerpt) . ' [...]';
  145. $commentdata['comment_content'] = addslashes($commentdata['comment_content']);
  146. $commentdata['comment_author'] = stripslashes($commentdata['comment_author']);
  147. $commentdata['comment_author'] = $this->convenc($commentdata['comment_author'], $blog_encoding, $from_encoding);
  148. $commentdata['comment_author'] = addslashes($commentdata['comment_author']);
  149. return $commentdata;
  150. }
  151. function preprocess_comment($commentdata) {
  152. if($commentdata['comment_type'] == 'trackback')
  153. return $this->incoming_trackback($commentdata);
  154. elseif($commentdata['comment_type'] == 'pingback')
  155. return $this->incoming_pingback($commentdata);
  156. else
  157. return $commentdata;
  158. }
  159. function is_almost_ascii($string, $encoding) {
  160. if(100 === $this->conf['ascii_threshold'])
  161. return false;
  162. return ($this->conf['ascii_threshold'] < round(@(mb_strlen($string, $encoding) / strlen($string)) * 100)) ? true : false;
  163. }
  164. function wp_trim_excerpt($text) {
  165. $raw_excerpt = $text;
  166. $blog_encoding = $this->blog_encoding;
  167. if('' == $text) {
  168. $text = get_the_content('');
  169. $text = strip_shortcodes( $text );
  170. $text = apply_filters('the_content', $text);
  171. $text = str_replace(']]>', ']]&gt;', $text);
  172. $text = strip_tags($text);
  173. $excerpt_length = apply_filters('excerpt_length', $this->conf['excerpt_length']);
  174. $excerpt_mblength = apply_filters('excerpt_mblength', $this->conf['excerpt_mblength']);
  175. $excerpt_more = apply_filters('excerpt_more', $this->conf['excerpt_more']);
  176. if($this->is_almost_ascii($text, $blog_encoding)) {
  177. $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
  178. if ( count($words) > $excerpt_length ) {
  179. array_pop($words);
  180. $text = implode(' ', $words);
  181. $text = $text . $excerpt_more;
  182. } else {
  183. $text = implode(' ', $words);
  184. }
  185. }
  186. else {
  187. $text = trim(preg_replace("/[\n\r\t ]+/", ' ', $text), ' ');
  188. if(mb_strlen($text, $blog_encoding) > $excerpt_mblength)
  189. $text = mb_substr($text, 0, $excerpt_mblength, $blog_encoding) . $excerpt_more;
  190. }
  191. }
  192. return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
  193. }
  194. function trim_multibyte_excerpt($text = '', $length = 110, $more = ' [...]', $encoding = 'UTF-8') {
  195. $text = strip_shortcodes($text);
  196. $text = str_replace(']]>', ']]&gt;', $text);
  197. $text = strip_tags($text);
  198. $text = trim(preg_replace("/[\n\r\t ]+/", ' ', $text), ' ');
  199. if(mb_strlen($text, $encoding) > $length)
  200. $text = mb_substr($text, 0, $length, $encoding) . $more;
  201. return $text;
  202. }
  203. function bp_create_excerpt($text = '') {
  204. if($this->is_almost_ascii($text, $this->blog_encoding))
  205. return $text;
  206. else
  207. return $this->trim_multibyte_excerpt($text, $this->conf['bp_excerpt_mblength'], $this->conf['bp_excerpt_more'], $this->blog_encoding);
  208. }
  209. function bp_get_activity_content_body($content = '') {
  210. return preg_replace("/<a [^<>]+>([^<>]+)<\/a>(" . preg_quote($this->conf['bp_excerpt_more'], '/') . "<\/p>)$/", "$1$2", $content);
  211. }
  212. // param $excerpt could already be truncated to 20 words or less by the original get_comment_excerpt() function.
  213. function get_comment_excerpt($excerpt = '') {
  214. $excerpt = preg_replace("/\.\.\.$/", '', $excerpt);
  215. $blog_encoding = $this->blog_encoding;
  216. if($this->is_almost_ascii($excerpt, $blog_encoding)) {
  217. $words = explode(' ', $excerpt, $this->conf['comment_excerpt_length'] + 1);
  218. if(count($words) > $this->conf['comment_excerpt_length']) {
  219. array_pop($words);
  220. $excerpt = implode(' ', $words) . '...';
  221. }
  222. }
  223. elseif(mb_strlen($excerpt, $blog_encoding) > $this->conf['comment_excerpt_mblength']) {
  224. $excerpt = mb_substr($excerpt, 0, $this->conf['comment_excerpt_mblength'], $blog_encoding) . '...';
  225. }
  226. return $excerpt;
  227. }
  228. function sanitize_file_name($name) {
  229. $info = pathinfo($name);
  230. $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
  231. $name = str_replace($ext, '', $name);
  232. $name_enc = rawurlencode($name);
  233. $name = ($name == $name_enc) ? $name . $ext : md5($name) . $ext;
  234. return $name;
  235. }
  236. function excerpt_mblength($length) {
  237. if(isset($this->query_based_vars['excerpt_mblength']) && (int) $this->query_based_vars['excerpt_mblength'])
  238. return $this->query_based_vars['excerpt_mblength'];
  239. else
  240. return (int) $length;
  241. }
  242. function excerpt_more($more) {
  243. if(isset($this->query_based_vars['excerpt_more']))
  244. return $this->query_based_vars['excerpt_more'];
  245. else
  246. return $more;
  247. }
  248. function query_based_settings() {
  249. $is_query_funcs = array('is_feed', 'is_404', 'is_search', 'is_tax', 'is_front_page', 'is_home', 'is_attachment', 'is_single', 'is_page', 'is_category', 'is_tag', 'is_author', 'is_date', 'is_archive', 'is_paged');
  250. foreach($is_query_funcs as $func) {
  251. if(isset($this->conf['excerpt_mblength.' . $func]) && !isset($this->query_based_vars['excerpt_mblength']) && $func())
  252. $this->query_based_vars['excerpt_mblength'] = $this->conf['excerpt_mblength.' . $func];
  253. if(isset($this->conf['excerpt_more.' . $func]) && !isset($this->query_based_vars['excerpt_more']) && $func())
  254. $this->query_based_vars['excerpt_more'] = $this->conf['excerpt_more.' . $func];
  255. }
  256. }
  257. function import_l10n_entry($text, $from_domain, $to_domain = 'default') {
  258. global $l10n;
  259. if(isset($l10n[$to_domain]->entries) && isset($l10n[$from_domain]->entries[$text]))
  260. $l10n[$to_domain]->entries[$text] = $l10n[$from_domain]->entries[$text];
  261. }
  262. function filters() {
  263. // remove filter
  264. if(false !== $this->conf['patch_wp_trim_excerpt'])
  265. remove_filter('get_the_excerpt', 'wp_trim_excerpt');
  266. // add filter
  267. add_filter('preprocess_comment', array(&$this, 'preprocess_comment'), 99);
  268. add_filter('excerpt_mblength', array(&$this, 'excerpt_mblength'), 9);
  269. add_filter('excerpt_more', array(&$this, 'excerpt_more'), 9);
  270. if(false !== $this->conf['patch_incoming_pingback'])
  271. add_filter('pre_remote_source', array(&$this, 'pre_remote_source'), 10, 2);
  272. if(false !== $this->conf['patch_wp_trim_excerpt'])
  273. add_filter('get_the_excerpt', array(&$this, 'wp_trim_excerpt'));
  274. if(false !== $this->conf['patch_get_comment_excerpt'])
  275. add_filter('get_comment_excerpt', array(&$this, 'get_comment_excerpt'));
  276. if(false !== $this->conf['patch_sanitize_file_name'])
  277. add_filter('sanitize_file_name', array(&$this, 'sanitize_file_name'));
  278. if(false !== $this->conf['patch_bp_create_excerpt']) {
  279. add_filter('bp_create_excerpt', array(&$this, 'bp_create_excerpt'), 99);
  280. add_filter('bp_get_activity_content_body', array(&$this, 'bp_get_activity_content_body'), 99);
  281. }
  282. // add action
  283. add_action('wp', array(&$this, 'query_based_settings'));
  284. if(method_exists($this, 'process_search_terms') && false !== $this->conf['patch_process_search_terms'])
  285. add_action('sanitize_comment_cookies', array(&$this, 'process_search_terms'));
  286. if(method_exists($this, 'wp_mail') && false !== $this->conf['patch_wp_mail'])
  287. add_action('phpmailer_init', array(&$this, 'wp_mail'));
  288. if(method_exists($this, 'admin_custom_css') && false !== $this->conf['patch_admin_custom_css'])
  289. add_action('admin_head' , array(&$this, 'admin_custom_css'), 99);
  290. if(method_exists($this, 'wplink_js') && false !== $this->conf['patch_wplink_js'])
  291. add_action('wp_default_scripts' , array(&$this, 'wplink_js'), 9);
  292. if(method_exists($this, 'word_count_js') && false !== $this->conf['patch_word_count_js'])
  293. add_action('wp_default_scripts' , array(&$this, 'word_count_js'), 9);
  294. }
  295. function mbfunctions_exist() {
  296. return (
  297. function_exists('mb_convert_encoding') &&
  298. function_exists('mb_convert_kana') &&
  299. function_exists('mb_detect_encoding') &&
  300. function_exists('mb_strcut') &&
  301. function_exists('mb_strlen') &&
  302. function_exists('mb_substr')
  303. ) ? true : false;
  304. }
  305. function activation_check() {
  306. global $wp_version;
  307. $required_version = $this->required_version;
  308. if(version_compare(substr($wp_version, 0, strlen($required_version)), $required_version, '<')) {
  309. deactivate_plugins(__FILE__);
  310. wp_die(sprintf(__('Sorry, WP Multibyte Patch requires WordPress %s or later.', 'wp-multibyte-patch'), $required_version));
  311. }
  312. elseif(!$this->has_mbfunctions) {
  313. deactivate_plugins(__FILE__);
  314. wp_die(__('Sorry, WP Multibyte Patch requires mbstring functions.', 'wp-multibyte-patch'));
  315. }
  316. }
  317. function load_conf() {
  318. $wpmp_conf = array();
  319. if(file_exists(WP_CONTENT_DIR . '/wpmp-config.php'))
  320. require_once(WP_CONTENT_DIR . '/wpmp-config.php');
  321. if(is_multisite()) {
  322. $blog_id = get_current_blog_id();
  323. if(file_exists(WP_CONTENT_DIR . '/wpmp-config-blog-' . $blog_id . '.php'))
  324. require_once(WP_CONTENT_DIR . '/wpmp-config-blog-' . $blog_id . '.php');
  325. }
  326. $this->conf = array_merge($this->conf, $wpmp_conf);
  327. }
  328. function __construct() {
  329. $this->load_conf();
  330. $this->blog_encoding = get_option('blog_charset');
  331. $this->has_mbfunctions = $this->mbfunctions_exist();
  332. load_textdomain($this->textdomain, plugin_dir_path(__FILE__) . $this->lang_dir . '/' . $this->textdomain . '-' . get_locale() . '.mo');
  333. register_activation_hook(__FILE__, array(&$this, 'activation_check'));
  334. $this->filters();
  335. }
  336. }
  337. if(defined('WP_PLUGIN_URL')) {
  338. global $wpmp;
  339. if(file_exists(dirname(__FILE__) . '/ext/' . get_locale() . '/class.php')) {
  340. require_once(dirname(__FILE__) . '/ext/' . get_locale() . '/class.php');
  341. $wpmp = new multibyte_patch_ext();
  342. }
  343. elseif(file_exists(dirname(__FILE__) . '/ext/default/class.php')) {
  344. require_once(dirname(__FILE__) . '/ext/default/class.php');
  345. $wpmp = new multibyte_patch_ext();
  346. }
  347. else
  348. $wpmp = new multibyte_patch();
  349. }
  350. ?>