PluginProbe
Content Censor / 2.6
Content Censor v2.6
trunk 1.0 1.1 1.2 2.0 2.01 2.05 2.1 2.11 2.20 2.25 2.26 2.27 2.28 2.3 2.31 2.32 2.33 2.4 2.41 2.42 2.43 2.44 2.45 2.46 All 39 releases
wp-content-filter / wp-content-filter.php

wp-content-filter.php in Content Censor 2.6, at wp-content-filter.php

474 lines 20.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: WP Content Filter
4 Plugin URI: http://wordpress.org/plugins/wp-content-filter/
5 Description: Censor and filter out profanity, swearing, abusive comments and any other keywords from your site.
6 Version: 2.6
7 Author: David Gwyer
8 Author URI: http://www.wpgoplugins.com
9 */
10
11 /* Copyright 2017 David Gwyer (email : david@wpgoplugins.com)
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 // pccf_ prefix is derived from [p]ress [c]oders [c]ontent [f]ilter
29 register_activation_hook( __FILE__, 'pccf_add_defaults' );
30 register_uninstall_hook( __FILE__, 'pccf_delete_plugin_options' );
31 add_action( 'admin_init', 'pccf_init' );
32 add_action( 'admin_menu', 'pccf_add_options_page' );
33 add_action( 'plugins_loaded', 'pccf_contfilt' );
34 add_filter( 'plugin_row_meta', 'pccf_plugin_action_links', 10, 2 );
35 add_filter( 'plugin_action_links', 'pccf_plugin_settings_link', 10, 2 );
36 add_action( 'admin_enqueue_scripts', 'pccf_register_admin_scripts' );
37 add_action( 'admin_notices', 'pccf_admin_notice' );
38 register_activation_hook( __FILE__, 'pccf_admin_notice_set_transient' );
39
40 /* Runs only when the plugin is activated. */
41 function pccf_admin_notice_set_transient() {
42
43 /* Create transient data */
44 set_transient( 'pccf-admin-notice', true, 5 );
45 }
46
47 /* Admin Notice on Activation. */
48 function pccf_admin_notice(){
49
50 /* Check transient, if available display notice */
51 if( get_transient( 'pccf-admin-notice' ) ){
52 ?>
53 <div class="updated notice is-dismissible">
54 <p><a href="https://wpgoplugins.com/plugins/content-censor/" target="_blank"><strong>WP Content Filter PRO</strong></a> is now available! Access great new features such as the batch processor to actively scan your entire site. *NEW* Filter BuddyPress content now too! <b>Try risk free today with our 100% money back guarantee! <span class="dashicons dashicons-smiley"></span></b></p>
55 </div>
56 <?php
57 /* Delete transient, only display this notice once. */
58 delete_transient( 'pccf-admin-notice' );
59 }
60 }
61
62 // Setup Plugin default options
63 global $pccf_defaults;
64 $pccf_defaults = array(
65 "chk_post_title" => "1",
66 "chk_post_content" => "1",
67 "chk_comments" => "1",
68 "txtar_keywords" => "Saturn, Jupiter, Pluto",
69 "txt_exclude" => "",
70 "rdo_word" => "all",
71 "drp_filter_char" => "star",
72 "rdo_case" => "insen",
73 "chk_default_options_db" => "",
74 "rdo_strict_filtering" => "strict_on"
75 );
76
77 // delete options table entries ONLY when plugin deactivated AND deleted
78 function pccf_delete_plugin_options() {
79 delete_option( 'pccf_options' );
80 }
81
82 // Define default option settings
83 function pccf_add_defaults() {
84
85 global $pccf_defaults;
86 $tmp = get_option( 'pccf_options', $pccf_defaults );
87
88 if ( ( ( isset( $tmp['chk_default_options_db'] ) && $tmp['chk_default_options_db'] == '1' ) ) || ( ! is_array( $tmp ) ) ) {
89 update_option( 'pccf_options', $pccf_defaults );
90 }
91 }
92
93 // Init plugin options to white list our options
94 function pccf_init() {
95 // put the below into a function and add checks all sections (especially radio buttons) have a valid choice (i.e. no section is blank)
96 // this is primarily to check newly added options have correct initial values
97 global $pccf_defaults;
98 $tmp = get_option( 'pccf_options', $pccf_defaults );
99
100 if ( ! $tmp['rdo_strict_filtering'] ) { // check strict filtering option has a starting value
101 $tmp["rdo_strict_filtering"] = "strict_off";
102 update_option( 'pccf_options', $tmp );
103 }
104 register_setting( 'pccf_plugin_options', 'pccf_options', 'pccf_validate_options' );
105 }
106
107 // Add menu page
108 function pccf_add_options_page() {
109
110 $page = add_options_page( 'WP Content Filter Options Page', 'WP Content Filter', 'manage_options', __FILE__, 'pccf_render_form' );
111
112 /* Enqueue scripts and styles for the theme option page */
113 add_action( "admin_print_styles-$page", 'pccf_theme_admin_styles' );
114 //add_action( "admin_print_scripts-$page", 'pccf_theme_admin_scripts' );
115 }
116
117 // Enqueue styles for theme options page.
118 function pccf_theme_admin_styles() {
119
120 /* Styles for plugin options page only. */
121 wp_enqueue_style( 'pccf-admin-css' );
122 }
123
124 // Draw the menu page itself
125 function pccf_render_form() {
126 ?>
127 <style>
128 a:focus{ box-shadow: none;}
129 .pcdm.dashicons { width: 32px; height: 32px; font-size: 32px; }
130 .pcdm.dashicons-yes { color: #1cc31c; }
131 .pcdm.dashicons-no { color: red; }
132 </style>
133 <div class="wrap">
134 <h2>WP Content Filter Options</h2>
135
136 <div class="notice" style="border: 2px #32cd32 solid;margin: 20px 0;">
137 <p>Upgrade to the Pro version and access great new features, such as the batch processor to actively scan your entire site. *NEW* Filter BuddyPress content now too! Try risk free today with our 100% money back guarantee! <span class="dashicons dashicons-smiley"></span></p>
138 <div style="display:flex;">
139 <div style="margin:15px 0;"><iframe width="350" height="197" src="https://www.youtube.com/embed/fBtf4QEhP2w" frameborder="0" allowfullscreen></iframe></div>
140 <div style="margin-left: 15px;">
141 <p><b>New feature in <a style="color:#32cd32;" href="https://wpgoplugins.com/plugins/content-censor/" target="_blank">Content Censor 0.4</a> <small>(13th March, 2017)</small> ignores censored keywords in HTML tags and attributes!</b></p>
142 <p>Occasionally you might have a keyword that is used as the source URL for an image or as part of a HTML link. Normally this will be censored too, breaking the link. But in <a style="color:#32cd32;" href="https://wpgoplugins.com/plugins/content-censor/" target="_blank">Content Censor 0.4</a> you can now optionally choose to ignore HTML tags and all their attributes.</p>
143 </div>
144 </div>
145 </div>
146
147 <form method="post" action="options.php">
148 <?php settings_fields( 'pccf_plugin_options' ); ?>
149 <?php
150 global $pccf_defaults;
151 $options = get_option( 'pccf_options', $pccf_defaults );
152 ?>
153 <table class="form-table">
154 <tr valign="top">
155 <th scope="row">Keywords to Remove</th>
156 <td>
157 <textarea name="pccf_options[txtar_keywords]" rows="7" cols="50" type='textarea'><?php echo $options['txtar_keywords']; ?></textarea>
158
159 <p class="description">Separate keywords with commas.</p>
160 </td>
161 </tr>
162 <tr valign="top">
163 <th scope="row">Exclude Pages</th>
164 <td>
165 <input type="text" class="regular-text code" name="pccf_options[txt_exclude]" value="<?php echo $options['txt_exclude']; ?>">
166
167 <p class="description">Enter a comma separate list of page ID's that will be excluded from the content filter.</p>
168 </td>
169 </tr>
170
171 <tr valign="top">
172 <th scope="row">Strict Filtering</th>
173 <td>
174 <label><input name="pccf_options[rdo_strict_filtering]" type="radio" value="strict_off" <?php checked( 'strict_off', $options['rdo_strict_filtering'] ); ?>> Strict Filtering OFF
175 <span style="font-family:lucida console;color:#888;margin-left:119px;">[e.g. 'ass' becomes 'p***able']</span></label><br>
176 <label><input name="pccf_options[rdo_strict_filtering]" type="radio" value="strict_on" <?php checked( 'strict_on', $options['rdo_strict_filtering'] ); ?>> Strict Filtering ON (recommended)
177 <span style="font-family:lucida console;color:#888;margin-left:32px;">[e.g. 'ass' becomes 'passable']</span></label>
178
179 <p class="description">Note: When strict filtering is ON, embedded keywords are no longer filtered.</p>
180 </td>
181 </tr>
182 <tr valign="top">
183 <th scope="row">Filter main content</th>
184 <td>
185 <label><input name="pccf_options[chk_post_content]" type="checkbox" value="1" <?php if ( isset( $options['chk_post_content'] ) ) {
186 checked( '1', $options['chk_post_content'] );
187 } ?>> Post Content/Excerpt<?php if ( class_exists( 'bbPress' ) ) {
188 echo " (including bbPress content)";
189 } ?></label><br>
190 <label><input name="pccf_options[chk_post_title]" type="checkbox" value="1" <?php if ( isset( $options['chk_post_title'] ) ) {
191 checked( '1', $options['chk_post_title'] );
192 } ?>> Post Titles<?php if ( class_exists( 'bbPress' ) ) {
193 echo " (including bbPress titles)";
194 } ?></label><br>
195 <label><input name="pccf_options[chk_comments]" type="checkbox" value="1" <?php if ( isset( $options['chk_comments'] ) ) {
196 checked( '1', $options['chk_comments'] );
197 } ?>> Comments <span class="description">(filters comment author names too)</span></label><br>
198 <label><input name="pccf_options[chk_tags]" type="checkbox" value="1" <?php if ( isset( $options['chk_tags'] ) ) {
199 checked( '1', $options['chk_tags'] );
200 } ?>> Tags</label><br>
201 <label><input name="pccf_options[chk_tag_cloud]" type="checkbox" value="1" <?php if ( isset( $options['chk_tag_cloud'] ) ) {
202 checked( '1', $options['chk_tag_cloud'] );
203 } ?>> Tag Cloud</label>
204 </td>
205 </tr>
206 <tr valign="top">
207 <th scope="row">Word Rendering</th>
208 <td>
209 <label><input name="pccf_options[rdo_word]" type="radio" value="first" <?php checked( 'first', $options['rdo_word'] ); ?>> First letter retained
210 <span style="font-family:lucida console;color:#888;margin-left:39px;">[e.g. 'dog' becomes 'd**']</span></label><br>
211 <label><input name="pccf_options[rdo_word]" type="radio" value="all" <?php checked( 'all', $options['rdo_word'] ); ?>> All letters removed
212 <span style="font-family:lucida console;color:#888;margin-left:40px;">[e.g. 'dog' becomes '***']</span></label><br>
213 <label><input name="pccf_options[rdo_word]" type="radio" value="firstlast" <?php checked( 'firstlast', $options['rdo_word'] ); ?>> First/last letter retained
214 <span style="font-family:lucida console;color:#888;margin-left:16px;">[e.g. 'dog' becomes 'd*g']</span></label>
215 </td>
216 </tr>
217 <tr valign="top">
218 <th scope="row">Filter Character</th>
219 <td>
220 <select name='pccf_options[drp_filter_char]'>
221 <option value='star' <?php selected( 'star', $options['drp_filter_char'] ); ?>>[*] Asterisk</option>
222 <option value='dollar' <?php selected( 'dollar', $options['drp_filter_char'] ); ?>>[$] Dollar</option>
223 <option value='question' <?php selected( 'question', $options['drp_filter_char'] ); ?>>[?] Question</option>
224 <option value='exclamation' <?php selected( 'exclamation', $options['drp_filter_char'] ); ?>>[!] Exclamation</option>
225 <option value='hyphen' <?php selected( 'hyphen', $options['drp_filter_char'] ); ?>>[-] Hyphen</option>
226 <option value='hash' <?php selected( 'hash', $options['drp_filter_char'] ); ?>>[#] Hash</option>
227 <option value='tilde' <?php selected( 'tilde', $options['drp_filter_char'] ); ?>>[~] Tilde</option>
228 <option value='blank' <?php selected( 'blank', $options['drp_filter_char'] ); ?>>[ ] Blank</option>
229 </select>
230
231 <p class="description">'Blank' completely removes the filtered keywords from view.</p>
232 </td>
233 </tr>
234 <tr valign="top">
235 <th scope="row">Case Matching</th>
236 <td>
237 <label><input name="pccf_options[rdo_case]" type="radio" value="sen" <?php checked( 'sen', $options['rdo_case'] ); ?>> Case Sensitive</label><br>
238 <label><input name="pccf_options[rdo_case]" type="radio" value="insen" <?php checked( 'insen', $options['rdo_case'] ); ?>> Case Insensitive (recommended)</label>
239
240 <p class="description">Note: 'Case Insensitive' matching type is better as it captures more words!</p>
241 </td>
242 </tr>
243 <tr valign="top">
244 <td colspan="2">
245 <div style="margin-top:10px;"></div>
246 </td>
247 </tr>
248 <tr valign="top" style="border-top:#dddddd 1px solid;">
249 <th scope="row">Database Options</th>
250 <td>
251 <label><input name="pccf_options[chk_default_options_db]" type="checkbox" value="1" <?php if ( isset( $options['chk_default_options_db'] ) ) {
252 checked( '1', $options['chk_default_options_db'] );
253 } ?>> Restore defaults upon plugin deactivation/reactivation</label>
254
255 <p class="description">Only check this if you want to reset plugin settings upon reactivation.</p>
256 </td>
257 </tr>
258 </table>
259 <p class="submit">
260 <input type="submit" class="button-primary" value="<?php _e( 'Save Changes' ) ?>">
261 </p>
262 </form>
263
264 <div style="margin-top:15px;">
265 <p style="margin-bottom:10px;">If you use this FREE Plugin on your website <b><em>please</em></b> consider making a <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BG4RPM3LLP5GU" target="_blank">donation</a> to support continued development. Thank you.<span style="margin-left:5px;" class="dashicons dashicons-smiley"></span></p>
266 </div>
267
268 <div style="clear:both;">
269 <span><a href="http://www.twitter.com/dgwyer" title="Follow us on Twitter" target="_blank"><img src="<?php echo plugins_url(); ?>/config-constants/images/twitter.png" /></a></span>
270 <span><a href="https://www.facebook.com/wpgoplugins/" title="Our Facebook page" target="_blank"><img src="<?php echo plugins_url(); ?>/config-constants/images/facebook.png" /></a></span>
271 <span><a href="https://www.youtube.com/channel/UCWzjTLWoyMgtIfpDgJavrTg" title="View our YouTube channel" target="_blank"><img src="<?php echo plugins_url(); ?>/config-constants/images/yt.png" /></a></span>
272 <span><a style="text-decoration:none;" title="Need help with ANY aspect of WordPress? We're here to help!" href="https://wpgoplugins.com/need-help-with-wordpress/" target="_blank"><span style="margin-left:-2px;color:#d41515;font-size:39px;line-height:32px;width:39px;height:39px;" class="dashicons dashicons-sos"></span></a></span>
273 <span style="margin-left:20px;"><input class="button" style="vertical-align:12px;" type="button" value="Visit Our Site" onClick="window.open('http://www.wpgoplugins.com')"></span>
274 <span style="margin-left:3px;"><input class="button" style="vertical-align:12px;" type="button" value="Subscribe (free)" title="Signup today for all the latest plugin news and updates!" onClick="window.open('http://eepurl.com/bXZmmD')"></span>
275 </div>
276
277 </div>
278 <?php
279 }
280
281 // Sanitize and validate input. Accepts an array, return a sanitized array.
282 function pccf_validate_options( $input ) {
283 // strip html from textboxes
284 $input['txtar_keywords'] = wp_filter_nohtml_kses( $input['txtar_keywords'] );
285 $input['txt_exclude'] = wp_filter_nohtml_kses( $input['txt_exclude'] );
286
287 return $input;
288 }
289
290 function pccf_contfilt() {
291
292 if ( is_admin() ) {
293 return;
294 } /* Only filter front end content. */
295
296 global $pccf_defaults;
297 $tmp = get_option( 'pccf_options', $pccf_defaults );
298
299 if ( isset( $tmp['chk_post_content'] ) ) {
300 if ( $tmp['chk_post_content'] == '1' ) {
301 add_filter( 'the_content', 'pccf_filter' );
302 add_filter( 'get_the_excerpt', 'pccf_filter' );
303 }
304
305 /* bbPress specific filtering (only if bbPress is present). */
306 if ( class_exists( 'bbPress' ) ) {
307 add_filter( 'bbp_get_topic_content', 'pccf_filter' );
308 add_filter( 'bbp_get_reply_content', 'pccf_filter' );
309 }
310 }
311 if ( isset( $tmp['chk_post_title'] ) ) {
312 if ( $tmp['chk_post_title'] == '1' ) {
313 add_filter( 'the_title', 'pccf_filter' );
314 }
315 }
316 if ( isset( $tmp['chk_comments'] ) ) {
317 if ( $tmp['chk_comments'] == '1' ) {
318 add_filter( 'comment_text', 'pccf_filter' );
319 }
320 }
321 if ( isset( $tmp['chk_comments'] ) ) {
322 if ( $tmp['chk_comments'] == '1' ) {
323 add_filter( 'get_comment_author', 'pccf_filter' );
324 }
325 }
326 if ( isset( $tmp['chk_tags'] ) ) {
327 if ( $tmp['chk_tags'] == '1' ) {
328 add_filter( 'term_links-post_tag', 'pccf_filter' );
329 }
330 }
331 if ( isset( $tmp['chk_cloud'] ) ) {
332 if ( $tmp['chk_cloud'] == '1' ) {
333 add_filter( 'wp_tag_cloud', 'pccf_filter' );
334 }
335 }
336 }
337
338 function pccf_filter( $text ) {
339
340 global $post;
341
342 // get comma separated list of page ID's to exclude
343 global $pccf_defaults;
344 $tmp = get_option( 'pccf_options', $pccf_defaults );
345
346 $exclude_id_list = $tmp['txt_exclude'];
347 $exclude_id_array = explode( ', ', $exclude_id_list );
348
349 // if current page ID is in exclude list then don't filter
350 if ( isset( $post ) && in_array( $post->ID, $exclude_id_array ) ) {
351 return $text;
352 }
353
354 $wildcard_filter_type = $tmp['rdo_word'];
355 $wildcard_char = $tmp['drp_filter_char'];
356
357 if ( $wildcard_char == 'star' ) {
358 $wildcard = '*';
359 } else {
360 if ( $wildcard_char == 'dollar' ) {
361 $wildcard = '$';
362 } else {
363 if ( $wildcard_char == 'question' ) {
364 $wildcard = '?';
365 } else {
366 if ( $wildcard_char == 'exclamation' ) {
367 $wildcard = '!';
368 } else {
369 if ( $wildcard_char == 'hyphen' ) {
370 $wildcard = '-';
371 } else {
372 if ( $wildcard_char == 'hash' ) {
373 $wildcard = '#';
374 } else {
375 if ( $wildcard_char == 'tilde' ) {
376 $wildcard = '~';
377 } else {
378 $wildcard = '';
379 }
380 }
381 }
382 }
383 }
384 }
385 }
386
387 $filter_type = $tmp['rdo_case'];
388 $db_search_string = $tmp['txtar_keywords'];
389 $keywords = array_map( 'trim', explode( ',', $db_search_string ) ); // explode and trim whitespace
390 $keywords = array_unique( $keywords ); // get rid of duplicates in the keywords textbox
391 $whole_word = $tmp['rdo_strict_filtering'] == 'strict_off' ? false : true;
392
393 foreach ( $keywords as $keyword ) {
394 $keyword = trim( $keyword ); // remove whitespace chars from start/end of string
395 if ( strlen( $keyword ) > 2 ) {
396 $replacement = censor_word($wildcard_filter_type, $keyword, $wildcard);
397 if ( $filter_type == "insen" ) {
398 $text = str_replace_word_i( $keyword, $replacement, $text, $wildcard_filter_type, $keyword, $wildcard, $whole_word );
399 } else {
400 $text = str_replace_word( $keyword, $replacement, $text, $whole_word );
401 }
402 }
403 }
404
405 return $text;
406 }
407
408 function censor_word( $wildcard_filter_type, $keyword, $wildcard ) {
409
410 if ( $wildcard_filter_type == 'first' ) {
411 $keyword = substr( $keyword, 0, 1 ) . str_repeat( $wildcard, strlen( substr( $keyword, 1 ) ) );
412 } else {
413 if ( $wildcard_filter_type == 'all' ) {
414 $keyword = str_repeat( $wildcard, strlen( substr( $keyword, 0 ) ) );
415 } else {
416 $keyword = substr( $keyword, 0, 1 ) . str_repeat( $wildcard, strlen( substr( $keyword, 2 ) ) ) . substr( $keyword, - 1, 1 );
417 }
418 }
419
420 return $keyword;
421 }
422
423 // case insensitive
424 function str_replace_word_i( $needle, $replacement, $haystack, $wildcard_filter_type, $keyword, $wildcard, $whole_word = true ) {
425
426 $needle = str_replace( '/', '\\/', preg_quote( $needle ) ); // allow '/' in keywords
427 $pattern = $whole_word ? "/\b$needle\b/i" : "/$needle/i";
428 $haystack = preg_replace_callback(
429 $pattern,
430 function($m) use($wildcard_filter_type, $keyword, $wildcard) {
431 return censor_word( $wildcard_filter_type, $m[0], $wildcard );
432 },
433 $haystack);
434
435 return $haystack;
436 }
437
438 // case sensitive
439 function str_replace_word( $needle, $replacement, $haystack, $whole_word = true ) {
440 $needle = str_replace( '/', '\\/', preg_quote( $needle ) ); // allow '/' in keywords
441 $pattern = $whole_word ? "/\b$needle\b/" : "/$needle/";
442 $haystack = preg_replace( $pattern, $replacement, $haystack );
443
444 return $haystack;
445 }
446
447 function pccf_plugin_action_links( $links, $file ) {
448
449 //if ( $file == plugin_basename( __FILE__ ) ) {
450 // add a link to pro plugin
451 //$links[] = '<a style="color:red;" href="https://wpgoplugins.com/plugins/content-censor/" target="_blank" title="Try out the Pro version today. Risk FREE - 100% money back guarantee!"><span class="dashicons dashicons-awards"></span></a>';
452 //}
453
454 return $links;
455 }
456
457 function pccf_plugin_settings_link( $links, $file ) {
458
459 if ( $file == plugin_basename( __FILE__ ) ) {
460 $pccf_links = '<a style="color:limegreen;" href="https://wpgoplugins.com/plugins/content-censor/" target="_blank" title="Upgrade to Pro - 100% money back guarantee"><span class="dashicons dashicons-awards"></span></a> | ';
461 $pccf_links .= '<a href="' . get_admin_url() . 'options-general.php?page=wp-content-filter/wp-content-filter.php">' . __( 'Settings' ) . '</a>';
462 // make the 'Settings' link appear first
463 array_unshift( $links, $pccf_links );
464 }
465
466 return $links;
467 }
468
469 // Register admin scripts and styles to be enqueued on the theme options page
470 function pccf_register_admin_scripts() {
471
472 // Register theme options page style sheets
473 wp_register_style( 'pccf-admin-css', plugins_url().'/wp-content-filter/css/pccf-admin.css' );
474 }