PluginProbe
Redirection / 2.3.11
Redirection v2.3.11
5.10.0 5.9.0 5.8.1 5.8.0 3.7.2 3.7.3 4.0 4.0.1 4.1 4.1.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.3.1 4.3.2 4.3.3 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6.2 4.7.1 All 130 releases
redirection / redirection.php

redirection.php in Redirection 2.3.11, at redirection.php

607 lines 19.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: Redirection
4 Plugin URI: http://urbangiraffe.com/plugins/redirection/
5 Description: Manage all your 301 redirects and monitor 404 errors
6 Version: 2.3.11
7 Author: John Godley
8 Author URI: http://urbangiraffe.com
9 ============================================================================================================
10 This software is provided "as is" and any express or implied warranties, including, but not limited to, the
11 implied warranties of merchantibility and fitness for a particular purpose are disclaimed. In no event shall
12 the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or
13 consequential damages(including, but not limited to, procurement of substitute goods or services; loss of
14 use, data, or profits; or business interruption) however caused and on any theory of liability, whether in
15 contract, strict liability, or tort(including negligence or otherwise) arising in any way out of the use of
16 this software, even if advised of the possibility of such damage.
17
18 For full license details see license.txt
19 ============================================================================================================
20 */
21
22 include dirname( __FILE__ ).'/plugin.php';
23 include dirname( __FILE__ ).'/models/redirect.php';
24 include dirname( __FILE__ ).'/models/match.php';
25 include dirname( __FILE__ ).'/models/log.php';
26 include dirname( __FILE__ ).'/models/group.php';
27 include dirname( __FILE__ ).'/models/module.php';
28 include dirname( __FILE__ ).'/models/action.php';
29 include dirname( __FILE__ ).'/models/monitor.php';
30 include dirname( __FILE__ ).'/modules/wordpress.php';
31
32 define( 'REDIRECTION_VERSION', '2.3.1' ); // DB schema version. Only change if DB needs changing
33
34 if ( class_exists( 'Redirection' ) )
35 return;
36
37 class Redirection extends Redirection_Plugin {
38 var $hasMatched = false;
39
40 function __construct() {
41 $this->register_plugin( 'redirection', __FILE__ );
42
43 if ( is_admin() ) {
44 $this->add_action( 'admin_menu' );
45 $this->add_action( 'load-tools_page_redirection', 'redirection_head' );
46
47 add_filter( 'set-screen-option', array( $this, 'set_per_page' ), 10, 3 );
48
49 $this->register_plugin_settings( __FILE__ );
50
51 add_action( 'wp_ajax_red_log_delete', array( &$this, 'ajax_log_delete' ) );
52 add_action( 'wp_ajax_red_module_edit', array( &$this, 'ajax_module_edit' ) );
53 add_action( 'wp_ajax_red_module_save', array( &$this, 'ajax_module_save' ) );
54 add_action( 'wp_ajax_red_group_edit', array( &$this, 'ajax_group_edit' ) );
55 add_action( 'wp_ajax_red_group_save', array( &$this, 'ajax_group_save' ) );
56 add_action( 'wp_ajax_red_redirect_add', array( &$this, 'ajax_redirect_add' ) );
57 add_action( 'wp_ajax_red_redirect_edit', array( &$this, 'ajax_redirect_edit' ) );
58 add_action( 'wp_ajax_red_redirect_save', array( &$this, 'ajax_redirect_save' ) );
59
60 $this->update();
61 }
62 else {
63 // Create a WordPress exporter and let it handle the load
64 $this->wp = new WordPress_Module();
65 $this->wp->start();
66 }
67
68 add_action( 'redirection_log_delete', array( $this, 'expire_logs' ) );
69
70 $this->monitor = new Red_Monitor( $this->get_options() );
71 $this->add_action ('template_redirect' );
72 }
73
74 function update() {
75 $version = get_option( 'redirection_version' );
76
77 if ( $version != REDIRECTION_VERSION ) {
78 include_once dirname( __FILE__ ).'/models/database.php';
79
80 $database = new RE_Database();
81 return $database->upgrade( $version, REDIRECTION_VERSION );
82 }
83
84 return true;
85 }
86
87 function set_per_page( $status, $option, $value ) {
88 if ( $option == 'redirection_log_per_page' )
89 return $value;
90 return $status;
91 }
92
93 function plugin_settings( $links ) {
94 $settings_link = '<a href="tools.php?page='.basename( __FILE__ ).'">'.__( 'Settings', 'redirection' ).'</a>';
95 array_unshift( $links, $settings_link );
96 return $links;
97 }
98
99 function version() {
100 $plugin_data = implode( '', file( __FILE__ ) );
101
102 if ( preg_match( '|Version:(.*)|i', $plugin_data, $version ) )
103 return trim( $version[1] );
104 return '';
105 }
106
107 function redirection_head() {
108 include dirname( __FILE__ ).'/models/pager.php';
109
110 $this->inject();
111
112 if ( !isset( $_GET['sub'] ) || ( isset( $_GET['sub'] ) && ( in_array( $_GET['sub'], array( 'log', '404s', 'groups' ) ) ) ) )
113 add_screen_option( 'per_page', array( 'label' => __( 'Log entries', 'redirection' ), 'default' => 25, 'option' => 'redirection_log_per_page' ) );
114
115 wp_enqueue_script( 'redirection', plugin_dir_url( __FILE__ ).'js/redirection.js', array( 'jquery-form', 'jquery-ui-sortable' ), $this->version() );
116 wp_enqueue_style( 'redirection', plugin_dir_url( __FILE__ ).'admin.css', $this->version() );
117
118 wp_localize_script( 'redirection', 'Redirectioni10n', array(
119 'error_msg' => __( 'Sorry, unable to do that. Please try refreshing the page.' ),
120 ) );
121 }
122
123 function admin_menu() {
124 add_management_page( __( "Redirection", 'redirection' ), __( "Redirection", 'redirection' ), apply_filters( 'redirection_role', 'administrator' ), basename( __FILE__ ), array( &$this, "admin_screen" ) );
125 }
126
127 function expire_logs() {
128 global $wpdb;
129
130 $options = $this->get_options();
131 $cleanup = false;
132
133 if ( $options['expire_redirect'] > 0 ) {
134 $cleanup = true;
135 $logs = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_logs WHERE created < DATE_SUB(NOW(), INTERVAL %d DAY)", $options['expire_redirect'] ) );
136 if ( $logs > 0 )
137 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_logs WHERE created < DATE_SUB(NOW(), INTERVAL %d DAY) LIMIT 1000", $options['expire_redirect'] ) );
138 }
139
140 if ( $options['expire_404'] > 0 ) {
141 $cleanup = true;
142 echo $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_404 WHERE created < DATE_SUB(NOW(), INTERVAL %d DAY)", $options['expire_404'] );
143 $l404 = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_404 WHERE created < DATE_SUB(NOW(), INTERVAL %d DAY)", $options['expire_404'] ) );
144
145 if ( $l404 > 0 )
146 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_404 WHERE created < DATE_SUB(NOW(), INTERVAL %d DAY) LIMIT 1000", $options['expire_404'] ) );
147 }
148
149 if ( $cleanup ) {
150 $rand = mt_rand( 1, 5000 );
151
152 if ( $rand == 11 )
153 $wpdb->query( "OPTIMIZE TABLE {$wpdb->prefix}redirection_logs" );
154 elseif ( $rand == 12 )
155 $wpdb->query( "OPTIMIZE TABLE {$wpdb->prefix}redirection_404" );
156 }
157 }
158
159 function admin_screen() {
160 $this->update();
161
162 $options = $this->get_options();
163 if ( ( $options['expire_404'] > 0 || $options['expire_redirect'] > 0 ) && !wp_next_scheduled( 'redirection_log_delete' ) )
164 wp_schedule_event( time(), 'daily', 'redirection_log_delete' );
165
166 if ( isset($_GET['sub']) ) {
167 if ( $_GET['sub'] == 'log' )
168 return $this->admin_screen_log();
169 elseif ( $_GET['sub'] == '404s' )
170 return $this->admin_screen_404();
171 elseif ( $_GET['sub'] == 'options' )
172 return $this->admin_screen_options();
173 elseif ( $_GET['sub'] == 'process' )
174 return $this->admin_screen_process();
175 elseif ( $_GET['sub'] == 'groups' )
176 return $this->admin_groups( isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0 );
177 elseif ( $_GET['sub'] == 'modules' )
178 return $this->admin_screen_modules();
179 elseif ( $_GET['sub'] == 'support' )
180 return $this->render_admin('support', array( 'options' => $this->get_options() ) );
181 }
182
183 return $this->admin_redirects( isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0 );
184 }
185
186 function admin_screen_modules() {
187 $options = $this->get_options();
188 $pager = new Redirection_Module_Table( $options['token'] );
189 $pager->prepare_items();
190
191 $this->render_admin( 'module_list', array( 'options' => $options, 'table' => $pager ) );
192 }
193
194 function get_options() {
195 $options = get_option( 'redirection_options' );
196 if ( $options === false )
197 $options = array();
198
199 $defaults = array(
200 'support' => false,
201 'token' => '',
202 'monitor_post' => 0,
203 'auto_target' => '',
204 'expire_redirect' => 7,
205 'expire_404' => 7,
206 );
207
208 foreach ( $defaults AS $key => $value ) {
209 if ( !isset( $options[$key] ) )
210 $options[$key] = $value;
211 }
212
213 if ( isset( $options['expire'] ) ) {
214 if ( isset( $options['log_redirection'] ) )
215 $options['expire_redirect'] = $options['expire'];
216
217 if ( isset( $options['log_404s'] ) )
218 $options['expire_404'] = $options['expire'];
219
220 unset( $options['expire'] );
221 unset( $options['log_redirection'] );
222 unset( $options['log_404s'] );
223
224 update_option( 'redirection_options', $options );
225 }
226
227 $options['lookup'] = 'http://urbangiraffe.com/map/?ip=';
228
229 return $options;
230 }
231
232 function inject() {
233 $options = $this->get_options();
234
235 if ( isset( $_POST['id'] ) && !isset( $_POST['action'] ) ) {
236 wp_safe_redirect( add_query_arg( 'id', intval( $_POST['id'] ), $_SERVER['REQUEST_URI'] ) );
237 die();
238 }
239
240 if ( isset( $_GET['token'] ) && isset( $_GET['page'] ) && isset( $_GET['sub'] ) && $_GET['token'] == $options['token'] && $_GET['page'] == 'redirection.php' ) {
241 include dirname( __FILE__ ).'/models/file_io.php';
242
243 $exporter = Red_FileIO::create( $_GET['sub'] );
244 if ( $exporter ) {
245 $items = Red_Item::get_all_for_module( intval( $_GET['module'] ) );
246
247 $exporter->export( $items );
248 die();
249 }
250 }
251 elseif ( isset( $_POST['export-csv'] ) && check_admin_referer( 'redirection-log_management' ) ) {
252 if ( isset( $_GET['sub'] ) && $_GET['sub'] == 'log' )
253 RE_Log::export_to_csv();
254 else
255 RE_404::export_to_csv();
256 die();
257 }
258 }
259
260 function admin_screen_options() {
261 if ( isset( $_POST['regenerate'] ) && check_admin_referer( 'redirection-update_options' ) ) {
262 $options = $this->get_options();
263 $options['token'] = md5( uniqid() );
264
265 update_option( 'redirection_options', $options );
266
267 $this->render_message( __( 'Your options were updated', 'redirection' ) );
268 }
269 elseif ( isset( $_POST['update'] ) && check_admin_referer( 'redirection-update_options' ) ) {
270 $options['monitor_post'] = stripslashes( $_POST['monitor_post'] );
271 $options['auto_target'] = stripslashes( $_POST['auto_target'] );
272 $options['support'] = isset( $_POST['support'] ) ? true : false;
273 $options['token'] = stripslashes( $_POST['token'] );
274 $options['expire_redirect'] = min( intval( $_POST['expire_redirect'] ), 60 );
275 $options['expire_404'] = min( intval( $_POST['expire_404'] ), 60 );
276
277 if ( trim( $options['token'] ) == '' )
278 $options['token'] = md5( uniqid() );
279
280 update_option( 'redirection_options', $options );
281
282 $this->render_message( __( 'Your options were updated', 'redirection' ) );
283 }
284 elseif ( isset( $_POST['delete'] ) && check_admin_referer( 'redirection-delete_plugin' ) ) {
285 include dirname( __FILE__ ).'/models/database.php';
286
287 $db = new RE_Database();
288 $db->remove( __FILE__ );
289
290 $this->render_message( __( 'Redirection data has been deleted and the plugin disabled', 'redirection' ) );
291 return;
292 }
293 elseif ( isset( $_POST['import'] ) && check_admin_referer( 'redirection-import' ) ) {
294 include dirname( __FILE__ ).'/models/file_io.php';
295
296 $count = Red_FileIO::import( $_POST['group'], $_FILES['upload'] );
297
298 if ( $count > 0 )
299 $this->render_message( sprintf( _n( '%d redirection was successfully imported','%d redirections were successfully imported', $count, 'redirection' ), $count ) );
300 else
301 $this->render_message( __( 'No items were imported', 'redirection' ) );
302 }
303
304 $groups = Red_Group::get_for_select();
305 $this->render_admin( 'options', array( 'options' => $this->get_options(), 'groups' => $groups ) );
306 }
307
308 function admin_screen_log() {
309 $options = $this->get_options();
310
311 if ( isset( $_POST['delete-all'] ) && check_admin_referer( 'redirection-log_management' ) ) {
312 RE_Log::delete_all();
313 $this->render_message( __( 'Your logs have been deleted', 'redirection' ) );
314 }
315
316 $table = new Redirection_Log_Table( $options );
317
318 if ( isset( $_GET['module'] ) )
319 $table->prepare_items( 'module', intval( $_GET['module'] ) );
320 else if (isset($_GET['group']))
321 $table->prepare_items( 'group', intval( $_GET['group'] ) );
322 else if (isset($_GET['redirect']))
323 $table->prepare_items( 'redirect', intval( $_GET['redirect'] ) );
324 else
325 $table->prepare_items();
326
327 $this->render_admin( 'log', array( 'options' => $options, 'table' => $table, 'lookup' => $options['lookup'], 'type' => 'log' ) );
328 }
329
330 function admin_screen_404() {
331 if ( isset( $_POST['delete-all'] ) && check_admin_referer( 'redirection-log_management' ) ) {
332 RE_404::delete_all();
333 $this->render_message( __( 'Your logs have been deleted', 'redirection' ) );
334 }
335
336 $options = $this->get_options();
337
338 $table = new Redirection_404_Table( $options );
339 $table->prepare_items( isset( $_GET['ip'] ) ? $_GET['ip'] : false );
340
341 $this->render_admin( 'log', array( 'options' => $options, 'table' => $table, 'lookup' => $options['lookup'], 'type' => '404s' ) );
342 }
343
344 function admin_groups( $module ) {
345 if ( isset( $_POST['add'] ) && check_admin_referer( 'redirection-add_group' ) ) {
346 if ( Red_Group::create( stripslashes_deep( $_POST ) ) ) {
347 $this->render_message( __( 'Your group was added successfully', 'redirection' ) );
348 Red_Module::flush( $module );
349 }
350 else
351 $this->render_error( __( 'Please specify a group name', 'redirection' ) );
352 }
353
354 if ( $module == 0 )
355 $module = Red_Module::get_first_id();
356
357 $table = new Redirection_Group_Table( Red_Module::get_for_select(), $module );
358 $table->prepare_items();
359
360 $module = Red_Module::get( $module );
361 if ( $module )
362 $this->render_admin( 'group_list', array( 'options' => $this->get_options(), 'table' => $table, 'modules' => Red_Module::get_for_select(), 'module' => $module ) );
363 else
364 $this->render_message( __( 'Unknown module', 'redirection' ) );
365 }
366
367 function admin_redirects( $group_id ) {
368 if ( $group_id == 0 )
369 $group_id = Red_Group::get_first_id();
370
371 $group = Red_Group::get( $group_id );
372 if ( $group === false ) {
373 $this->render_error( __( 'Invalid group ID', 'redirection' ) );
374 }
375 else {
376 $table = new Redirection_Table( Red_Group::get_for_select(), $group );
377 $table->prepare_items();
378
379 $this->render_admin( 'item_list', array( 'options' => $this->get_options(), 'group' => $group, 'table' => $table, 'date_format' => get_option( 'date_format' ) ) );
380 }
381 }
382
383 function setMatched( $match ) {
384 $this->hasMatched = $match;
385 }
386
387 function hasMatched() {
388 return $this->hasMatched;
389 }
390
391 function locales() {
392 $locales = array();
393 if ( file_exists( dirname( __FILE__ ).'/readme.txt' ) ) {
394 $readme = file_get_contents( dirname( __FILE__ ).'/readme.txt' );
395
396 $start = strpos( $readme, 'Redirection is available in' );
397 $end = strpos( $readme, '==', $start );
398 if ( $start !== false && $end !== false ) {
399 if ( preg_match_all( '/^\* (.*?) by (.*?)/m', substr( $readme, $start, $end ), $matches ) > 0 ) {
400 $locales = $matches[1];
401 }
402 }
403
404 sort( $locales );
405 }
406
407 return $locales;
408 }
409
410 /**
411 * Matches 404s
412 */
413 function template_redirect() {
414 if ( is_404() ) {
415 $options = $this->get_options();
416
417 if ( isset( $options['expire_404'] ) && $options['expire_404'] >= 0 ) {
418 RE_404::create( red_get_url(), red_user_agent(), red_ip(), red_http_referrer() );
419 }
420 }
421 }
422
423 public function ajax_log_delete() {
424 if ( check_ajax_referer( 'redirection-items' ) ) {
425 if ( preg_match_all( '/=(\d*)/', $_POST['checked'], $items ) > 0) {
426 foreach ( $items[1] AS $item ) {
427 RE_Log::delete( intval( $item ) );
428 }
429 }
430 }
431 }
432
433 private function check_ajax_referer( $nonce ) {
434 if ( check_ajax_referer( $nonce, 'nonce', false ) === false )
435 $this->output_ajax_response( array( 'error' => __( 'Unable to perform action' ).' - bad nonce' ) );
436 }
437
438 public function ajax_module_edit() {
439 $module_id = intval( $_POST['id'] );
440
441 $this->check_ajax_referer( 'red_edit-'.$module_id );
442
443 $module = Red_Module::get( $module_id );
444 if ( $module )
445 $json['html'] = $this->capture_admin( 'module_edit', array( 'module' => $module ) );
446 else
447 $json['error'] = __( 'Unable to perform action' ).' - could not find module';
448
449 $this->output_ajax_response( $json );
450 }
451
452 public function ajax_module_save() {
453 global $hook_suffix;
454
455 include dirname( __FILE__ ).'/models/pager.php';
456
457 $hook_suffix = '';
458 $module_id = intval( $_POST['id'] );
459 $options = $this->get_options();
460
461 $this->check_ajax_referer( 'red_module_save_'.$module_id );
462
463 $module = Red_Module::get( $module_id );
464
465 if ( $module ) {
466 $module->update( $_POST );
467
468 $pager = new Redirection_Module_Table( $options['token'] );
469 $json = array( 'html' => $pager->column_name( $module ) );
470 }
471 else
472 $json['error'] = __( 'Unable to perform action' ).' - could not find module';
473
474 $this->output_ajax_response( $json );
475 }
476
477 public function ajax_group_edit() {
478 $group_id = intval( $_POST['id'] );
479
480 $this->check_ajax_referer( 'red-edit_'.$group_id );
481
482 $group = Red_Group::get( $group_id );
483 if ( $group )
484 $json['html'] = $this->capture_admin( 'group_edit', array( 'group' => $group, 'modules' => Red_Module::get_for_select() ) );
485 else
486 $json['error'] = __( 'Unable to perform action' ).' - could not find group';
487
488 $this->output_ajax_response( $json );
489 }
490
491 public function ajax_group_save() {
492 global $hook_suffix;
493
494 include dirname( __FILE__ ).'/models/pager.php';
495
496 $hook_suffix = '';
497 $group_id = intval( $_POST['id'] );
498
499 $this->check_ajax_referer( 'redirection-group_save_'.$group_id );
500
501 $group = Red_Group::get( $group_id );
502 if ( $group ) {
503 $group->update( $_POST );
504
505 $pager = new Redirection_Group_Table( array(), false );
506 $json = array( 'html' => $pager->column_name( $group ) );
507 }
508 else
509 $json['error'] = __( 'Unable to perform action' ).' - could not find redirect';
510
511 $this->output_ajax_response( $json );
512 }
513
514 public function ajax_redirect_edit() {
515 $this->check_ajax_referer( 'red-edit_'.intval( $_POST['id'] ) );
516 $redirect = Red_Item::get_by_id( intval( $_POST['id'] ) );
517
518 if ( $redirect )
519 $json['html'] = $this->capture_admin( 'item_edit', array( 'redirect' => $redirect, 'groups' => Red_Group::get_for_select() ) );
520 else
521 $json['error'] = __( 'Unable to perform action' ).' - could not find redirect';
522
523 $this->output_ajax_response( $json );
524 }
525
526 public function ajax_redirect_save() {
527 global $hook_suffix;
528
529 include dirname( __FILE__ ).'/models/pager.php';
530
531 $hook_suffix = '';
532
533 $red_id = intval( $_POST['id'] );
534
535 $this->check_ajax_referer( 'redirection-redirect_save_'.$red_id );
536
537 $redirect = Red_Item::get_by_id( $red_id );
538 if ( $redirect ) {
539 $redirect->update( $_POST );
540
541 $pager = new Redirection_Table( array() );
542 $json = array( 'html' => $pager->column_url( $redirect ), 'code' => $redirect->get_action_code() );
543 }
544 else
545 $json['error'] = __( 'Unable to perform action' ).' - could not find redirect';
546
547 $this->output_ajax_response( $json );
548 }
549
550 public function ajax_redirect_add() {
551 global $hook_suffix;
552
553 include dirname( __FILE__ ).'/models/pager.php';
554
555 $hook_suffix = '';
556
557 $this->check_ajax_referer( 'redirection-redirect_add' );
558
559 $item = Red_Item::create( $_POST );
560 if ( is_wp_error( $item ) )
561 $json['error'] = $item->get_error_message();
562 elseif ( $item !== false ) {
563 $pager = new Redirection_Table( array() );
564 $json = array( 'html' => $pager->get_row( $item ) );
565 }
566 else
567 $json['error'] = __( 'Sorry, but your redirection was not created', 'redirection' );
568
569 $this->output_ajax_response( $json );
570 }
571
572 private function output_ajax_response( array $data ) {
573 header( 'Content-Type: application/json' );
574 echo json_encode( $data );
575 die();
576 }
577 }
578
579 function red_get_url() {
580 if ( isset( $_SERVER['REQUEST_URI'] ) )
581 return $_SERVER['REQUEST_URI'];
582 return '';
583 }
584
585 function red_user_agent() {
586 if ( isset( $_SERVER['HTTP_USER_AGENT'] ) )
587 return $_SERVER['HTTP_USER_AGENT'];
588 return false;
589 }
590
591 function red_http_referrer() {
592 if ( isset( $_SERVER['HTTP_REFERER'] ) )
593 return $_SERVER['HTTP_REFERER'];
594 return false;
595 }
596
597 function red_ip() {
598 if ( isset( $_SERVER['REMOTE_ADDR'] ) )
599 return $_SERVER['REMOTE_ADDR'];
600 elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
601 return $_SERVER['HTTP_X_FORWARDED_FOR'];
602 return '';
603 }
604
605 // Instantiate the plugin
606 $redirection = new Redirection;
607