PageRenderTime 50ms CodeModel.GetById 2ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-multibyte-patch/wp-multibyte-patch.php

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