PluginProbe
Redirection / 2.3.9
Redirection v2.3.9
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.9, at redirection.php

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