PluginProbe
Redirection / 2.6
Redirection v2.6
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 / models / redirect.php

redirect.php in Redirection 2.6, at models/redirect.php

487 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Red_Item {
4 private $id = null;
5 private $created;
6 private $referrer;
7 private $url = null;
8 private $regex = false;
9 private $action_data = null;
10 private $action_code = 0;
11 private $action_type;
12 private $match_type;
13 private $title;
14 private $last_access = null;
15 private $last_count = 0;
16 private $tracking = true;
17 private $status;
18 private $position;
19 private $group_id;
20
21 function __construct( $values, $type = '', $match = '' ) {
22 if ( is_object( $values ) ) {
23 foreach ( $values as $key => $value ) {
24 $this->$key = $value;
25 }
26
27 if ( $this->match_type === '' ) {
28 $this->match_type = 'url';
29 }
30
31 $this->regex = (bool)$this->regex;
32 $this->match = Red_Match::create( $this->match_type, $this->action_data );
33 $this->match->id = $this->id;
34 $this->match->action_code = $this->action_code;
35
36 $action = false;
37
38 if ( $this->action_type ) {
39 $action = Red_Action::create( $this->action_type, $this->action_code );
40 }
41
42 if ( $action ) {
43 $this->action = $action;
44 $this->match->action = $this->action;
45 }
46 else
47 $this->action = Red_Action::create( 'nothing', 0 );
48
49 if ( $this->last_access === '0000-00-00 00:00:00' )
50 $this->last_access = 0;
51 else
52 $this->last_access = mysql2date( 'U', $this->last_access );
53 }
54 else {
55 $this->url = $values;
56 $this->type = $type;
57 $this->match = $match;
58 }
59 }
60
61 static function get_all_for_module( $module ) {
62 global $wpdb;
63
64 $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.tracking FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE {$wpdb->prefix}redirection_items.status='enabled' ORDER BY {$wpdb->prefix}redirection_groups.position,{$wpdb->prefix}redirection_items.position", $module );
65
66 $rows = $wpdb->get_results( $sql );
67 $items = array();
68 if ( count( $rows ) > 0 ) {
69 foreach ( $rows as $row ) {
70 $items[] = new Red_Item( $row );
71 }
72 }
73
74 return $items;
75 }
76
77 static function get_for_url( $url, $type ) {
78 global $wpdb;
79
80 $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.position AS group_pos FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE ({$wpdb->prefix}redirection_items.regex=1 OR {$wpdb->prefix}redirection_items.url=%s)", WordPress_Module::MODULE_ID, $url );
81
82 $rows = $wpdb->get_results( $sql );
83 $items = array();
84 if ( count( $rows ) > 0 ) {
85 foreach ( $rows as $row ) {
86 $items[] = array( 'position' => ( $row->group_pos * 1000 ) + $row->position, 'item' => new Red_Item( $row ) );
87 }
88 }
89
90 usort( $items, array( 'Red_Item', 'sort_urls' ) );
91 $items = array_map( array( 'Red_Item', 'reduce_sorted_items' ), $items );
92
93 // Sort it in PHP
94 ksort( $items );
95 $items = array_values( $items );
96 return $items;
97 }
98
99 static function sort_urls( $first, $second ) {
100 if ( $first['position'] === $second['position'] )
101 return 0;
102
103 return ($first['position'] < $second['position']) ? -1 : 1;
104 }
105
106 static function reduce_sorted_items( $item ) {
107 return $item['item'];
108 }
109
110 static function get_by_module( $module ) {
111 global $wpdb;
112
113 $sql = "SELECT {$wpdb->prefix}redirection_items.* FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id";
114 $sql .= $wpdb->prepare( " WHERE {$wpdb->prefix}redirection_groups.module_id=%d", $module );
115
116 $rows = $wpdb->get_results( $sql );
117 $items = array();
118
119 foreach ( (array) $rows as $row ) {
120 $items[] = new Red_Item( $row );
121 }
122
123 return $items;
124 }
125
126 static function get_by_id( $id ) {
127 global $wpdb;
128
129 $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}redirection_items WHERE id=%d", $id ) );
130 if ( $row )
131 return new Red_Item( $row );
132 return false;
133 }
134
135 static function auto_generate() {
136 $options = red_get_options();
137 $id = time();
138
139 $url = $options['auto_target'];
140 $url = str_replace( '$dec$', $id, $url );
141 $url = str_replace( '$hex$', sprintf( '%x', $id ), $url );
142 return $url;
143 }
144
145 static function create( array $details ) {
146 global $wpdb;
147
148 $details = array_map( 'trim', $details );
149 $details = array_map( 'stripslashes', $details );
150
151 // Auto generate URLs
152 if ( empty( $details['source'] ) )
153 $details['source'] = self::auto_generate();
154
155 if ( empty( $details['target'] ) )
156 $details['target'] = self::auto_generate();
157
158 // Make sure we don't redirect to ourself
159 if ( $details['source'] === $details['target'] )
160 return new WP_Error( 'redirect-add', __( 'Source and target URL must be different', 'redirection' ) );
161
162 $parsed_url = parse_url( $details['source'] );
163 $parsed_domain = parse_url( site_url() );
164
165 if ( isset( $parsed_url['scheme'] ) && ( $parsed_url['scheme'] === 'http' || $parsed_url['scheme'] === 'https' ) && $parsed_url['host'] !== $parsed_domain['host'] ) {
166 return new WP_Error( 'redirect-add', sprintf( __( 'You can only redirect from a relative URL (<code>%s</code>) on this domain (<code>%s</code>).', 'redirection' ), $parsed_url['path'], $parsed_domain['host'] ) );
167 }
168
169 $matcher = Red_Match::create( $details['match'] );
170 $group_id = intval( $details['group_id'] );
171 $group = Red_Group::get( $group_id );
172
173 if ( $group_id <= 0 || ! $group )
174 return new WP_Error( 'redirect-add', __( 'Invalid group when creating redirect', 'redirection' ) );
175
176 if ( ! $matcher )
177 return new WP_Error( 'redirect-add', __( 'Invalid source URL when creating redirect for given match type', 'redirection' ) );
178
179 $regex = ( isset( $details['regex'] ) && (bool) $details['regex'] !== false ) ? 1 : 0;
180 $position = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $group_id ) );
181
182 $action = $details['red_action'];
183 $action_code = 0;
184 if ( $action === 'url' || $action === 'random' )
185 $action_code = 301;
186 elseif ( $action === 'error' )
187 $action_code = 404;
188
189 if ( isset( $details['action_code'] ) )
190 $action_code = intval( $details['action_code'] );
191
192 $data = array(
193 'url' => self::sanitize_url( $details['source'], $regex ),
194 'action_type' => $details['red_action'],
195 'regex' => $regex,
196 'position' => $position,
197 'match_type' => $details['match'],
198 'action_data' => $matcher->data( $details ),
199 'action_code' => $action_code,
200 'last_access' => '0000-00-00 00:00:00',
201 'group_id' => $group_id,
202 );
203
204 $data = apply_filters( 'redirection_create_redirect', $data );
205
206 $wpdb->delete( $wpdb->prefix.'redirection_items', array( 'url' => $data['action_data'], 'action_type' => $data['action_type'], 'action_data' => $data['url'] ) );
207
208 if ( $wpdb->insert( $wpdb->prefix.'redirection_items', $data ) ) {
209 Red_Module::flush( $group_id );
210 return self::get_by_id( $wpdb->insert_id );
211 }
212
213 return new WP_Error( 'redirect-add', __( 'Unable to add new redirect - delete Redirection from the options page and re-install' ) );
214 }
215
216 public function delete() {
217 global $wpdb;
218
219 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_items WHERE id=%d", $this->id ) );
220
221 RE_Log::delete_for_id( $this->id );
222
223 // Reorder all elements
224 $rows = $wpdb->get_results( "SELECT id FROM {$wpdb->prefix}redirection_items ORDER BY position" );
225 if ( count( $rows ) > 0 ) {
226 foreach ( $rows as $pos => $row ) {
227 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'position' => $pos ), array( 'id' => $row->id ) );
228 }
229 }
230
231 Red_Module::flush( $this->group_id );
232 }
233
234 static function sanitize_url( $url, $regex = false ) {
235 // Make sure that the old URL is relative
236 $url = preg_replace( '@^https?://(.*?)/@', '/', $url );
237 $url = preg_replace( '@^https?://(.*?)$@', '/', $url );
238
239 // No hash
240 $url = preg_replace( '/#.*$/', '', $url );
241
242 // No new lines
243 $url = preg_replace( "/[\r\n\t].*?$/s", '', $url );
244
245 // Clean control codes
246 $url = preg_replace( '/[^\PC\s]/u', '', $url );
247
248 // Ensure a slash at start
249 if ( substr( $url, 0, 1 ) !== '/' && $regex === false )
250 $url = '/'.$url;
251
252 return $url;
253 }
254
255 function update( $details ) {
256 if ( strlen( $details['old'] ) > 0 ) {
257 global $wpdb;
258
259 $details = array_map( 'stripslashes', $details );
260
261 $this->regex = isset( $details['regex'] ) ? 1 : 0;
262 $this->url = self::sanitize_url( $details['old'], $this->regex );
263 $this->title = $details['title'];
264
265 $data = $this->match->data( $details );
266
267 $this->action_code = 0;
268 if ( isset( $details['action_code'] ) )
269 $this->action_code = intval( $details['action_code'] );
270
271 $old_group = false;
272 if ( isset( $details['group_id'] ) ) {
273 $old_group = intval( $this->group_id );
274 $this->group_id = intval( $details['group_id'] );
275 }
276
277 // Save this
278 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'url' => $this->url, 'regex' => $this->regex, 'action_code' => $this->action_code, 'action_data' => $data, 'group_id' => $this->group_id, 'title' => $this->title ), array( 'id' => $this->id ) );
279
280 Red_Module::flush( $this->group_id );
281
282 if ( $old_group !== $this->group_id ) {
283 Red_Module::flush( $old_group );
284 }
285 }
286 }
287
288 static function save_order( $items, $start ) {
289 global $wpdb;
290
291 foreach ( $items as $pos => $id ) {
292 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'position' => $pos + $start ), array( 'id' => $id ) );
293 }
294
295 Red_Module::flush( $this->group_id );
296 }
297
298 function matches( $url ) {
299 $this->url = str_replace( ' ', '%20', $this->url );
300 $matches = false;
301
302 // Check if we match the URL
303 if ( ( $this->regex === false && ( $this->url === $url || $this->url === rtrim( $url, '/' ) || $this->url === urldecode( $url ) ) ) || ( $this->regex === true && @preg_match( '@'.str_replace( '@', '\\@', $this->url ).'@', $url, $matches ) > 0) || ( $this->regex === true && @preg_match( '@'.str_replace( '@', '\\@', $this->url ).'@', urldecode( $url ), $matches ) > 0) ) {
304 // Check if our match wants this URL
305 $target = $this->match->get_target( $url, $this->url, $this->regex );
306
307 if ( $target ) {
308 $target = $this->replace_special_tags( $target );
309
310 $this->visit( $url, $target );
311
312 if ( $this->status === 'enabled' )
313 return $this->action->process_before( $this->action_code, $target );
314 }
315 }
316
317 return false;
318 }
319
320 function replace_special_tags( $target ) {
321 if ( is_numeric( $target ) )
322 $target = get_permalink( $target );
323 else {
324 $user = wp_get_current_user();
325 if ( ! empty( $user ) ) {
326 $target = str_replace( '%userid%', $user->ID, $target );
327 $target = str_replace( '%userlogin%', isset( $user->user_login ) ? $user->user_login : '', $target );
328 $target = str_replace( '%userurl%', isset( $user->user_url ) ? $user->user_url : '', $target );
329 }
330 }
331
332 return $target;
333 }
334
335 function visit( $url, $target ) {
336 if ( $this->tracking && $this->id ) {
337 global $wpdb;
338
339 // Update the counters
340 $count = $this->last_count + 1;
341 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}redirection_items SET last_count=%d, last_access=NOW() WHERE id=%d", $count, $this->id ) );
342
343 $options = red_get_options();
344 if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] >= 0 ) {
345 $log = RE_Log::create( $url, $target, $this->get_user_agent(), $this->get_ip(), $this->get_referrer(), array( 'redirect_id' => $this->id, 'group_id' => $this->group_id ) );
346 }
347 }
348 }
349
350 private function get_ip() {
351 if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
352 return $_SERVER['HTTP_X_FORWARDED_FOR'];
353 elseif ( isset( $_SERVER['REMOTE_ADDR'] ) )
354 return $_SERVER['REMOTE_ADDR'];
355 return '';
356 }
357
358 private function get_referrer() {
359 if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
360 return $_SERVER['HTTP_REFERER'];
361 }
362
363 return '';
364 }
365
366 private function get_user_agent() {
367 if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
368 return $_SERVER['HTTP_USER_AGENT'];
369 }
370
371 return '';
372 }
373
374 public function is_enabled() {
375 return $this->status === 'enabled';
376 }
377
378 function reset() {
379 global $wpdb;
380
381 $this->last_count = 0;
382 $this->last_access = '0000-00-00 00:00:00';
383
384 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'last_count' => 0, 'last_access' => $this->last_access ), array( 'id' => $this->id ) );
385
386 RE_Log::delete_for_id( $this->id );
387 }
388
389 function show_url( $url ) {
390 return implode( '&#8203;/', explode( '/', $url ) );
391 }
392
393 function move_to( $group ) {
394 global $wpdb;
395
396 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'group_id' => $group ), array( 'id' => $this->id ) );
397 }
398
399 public function enable() {
400 global $wpdb;
401
402 $this->status = 'enabled';
403 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
404 }
405
406 public function disable() {
407 global $wpdb;
408
409 $this->status = 'disabled';
410 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
411 }
412
413 static function actions( $action = '' ) {
414 $actions = array(
415 'url' => __( 'Redirect to URL', 'redirection' ),
416 'random' => __( 'Redirect to random post', 'redirection' ),
417 'pass' => __( 'Pass-through', 'redirection' ),
418 'error' => __( 'Error (404)', 'redirection' ),
419 'nothing' => __( 'Do nothing', 'redirection' ),
420 );
421
422 if ( $action )
423 return $actions[ $action ];
424 return $actions;
425 }
426
427 function match_name() {
428 return $this->match->match_name();
429 }
430
431 function type() {
432 if ( ( $this->action_type === 'url' || $this->action_type === 'error' || $this->action_type === 'random' ) && $this->action_code > 0 )
433 return $this->action_code;
434 else if ( $this->action_type === 'pass' )
435 return 'pass';
436 return '&mdash;';
437 }
438
439 public function get_id() {
440 return $this->id;
441 }
442
443 public function get_position() {
444 return $this->position;
445 }
446
447 public function get_group_id() {
448 return $this->group_id;
449 }
450
451 public function get_url() {
452 return $this->url;
453 }
454
455 public function get_title() {
456 return $this->title;
457 }
458
459 public function get_hits() {
460 return $this->last_count;
461 }
462
463 public function get_last_hit() {
464 return $this->last_access;
465 }
466
467 public function is_regex() {
468 return $this->regex ? true : false;
469 }
470
471 public function get_match_type() {
472 return $this->match_type;
473 }
474
475 public function get_action_type() {
476 return $this->action_type;
477 }
478
479 public function get_action_code() {
480 return intval( $this->action_code );
481 }
482
483 public function get_action_data() {
484 return $this->action_data;
485 }
486 }
487