PluginProbe
Redirection / 2.4.5
Redirection v2.4.5
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.4.5, at models/redirect.php

466 lines 14.3 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'];
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'] ) && $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 if ( $old_group !== $this->group_id ) {
281 Red_Module::flush( $this->group_id );
282 Red_Module::flush( $old_group );
283 }
284 }
285 }
286
287 static function save_order( $items, $start ) {
288 global $wpdb;
289
290 foreach ( $items as $pos => $id ) {
291 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'position' => $pos + $start ), array( 'id' => $id ) );
292 }
293
294 Red_Module::flush( $this->group_id );
295 }
296
297 function matches( $url ) {
298 $this->url = str_replace( ' ', '%20', $this->url );
299 $matches = false;
300
301 // Check if we match the URL
302 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) ) {
303 // Check if our match wants this URL
304 $target = $this->match->get_target( $url, $this->url, $this->regex );
305
306 if ( $target ) {
307 $target = $this->replace_special_tags( $target );
308
309 $this->visit( $url, $target );
310
311 if ( $this->status === 'enabled' )
312 return $this->action->process_before( $this->action_code, $target );
313 }
314 }
315
316 return false;
317 }
318
319 function replace_special_tags( $target ) {
320 if ( is_numeric( $target ) )
321 $target = get_permalink( $target );
322 else {
323 $user = wp_get_current_user();
324 if ( ! empty( $user ) ) {
325 $target = str_replace( '%userid%', $user->ID, $target );
326 $target = str_replace( '%userlogin%', isset( $user->user_login ) ? $user->user_login : '', $target );
327 $target = str_replace( '%userurl%', isset( $user->user_url ) ? $user->user_url : '', $target );
328 }
329 }
330
331 return $target;
332 }
333
334 function visit( $url, $target ) {
335 if ( $this->tracking && $this->id ) {
336 global $wpdb, $redirection;
337
338 // Update the counters
339 $count = $this->last_count + 1;
340 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}redirection_items SET last_count=%d, last_access=NOW() WHERE id=%d", $count, $this->id ) );
341
342 if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
343 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
344 elseif ( isset( $_SERVER['REMOTE_ADDR'] ) )
345 $ip = $_SERVER['REMOTE_ADDR'];
346
347 $options = red_get_options();
348 if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] >= 0 )
349 $log = RE_Log::create( $url, $target, $_SERVER['HTTP_USER_AGENT'], $ip, isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '', array( 'redirect_id' => $this->id, 'group_id' => $this->group_id ) );
350 }
351 }
352
353 public function is_enabled() {
354 return $this->status === 'enabled';
355 }
356
357 function reset() {
358 global $wpdb;
359
360 $this->last_count = 0;
361 $this->last_access = '0000-00-00 00:00:00';
362
363 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'last_count' => 0, 'last_access' => $this->last_access ), array( 'id' => $this->id ) );
364
365 RE_Log::delete_for_id( $this->id );
366 }
367
368 function show_url( $url ) {
369 return implode( '&#8203;/', explode( '/', $url ) );
370 }
371
372 function move_to( $group ) {
373 global $wpdb;
374
375 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'group_id' => $group ), array( 'id' => $this->id ) );
376 }
377
378 public function enable() {
379 global $wpdb;
380
381 $this->status = 'enabled';
382 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
383 }
384
385 public function disable() {
386 global $wpdb;
387
388 $this->status = 'disabled';
389 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
390 }
391
392 static function actions( $action = '' ) {
393 $actions = array(
394 'url' => __( 'Redirect to URL', 'redirection' ),
395 'random' => __( 'Redirect to random post', 'redirection' ),
396 'pass' => __( 'Pass-through', 'redirection' ),
397 'error' => __( 'Error (404)', 'redirection' ),
398 'nothing' => __( 'Do nothing', 'redirection' ),
399 );
400
401 if ( $action )
402 return $actions[ $action ];
403 return $actions;
404 }
405
406 function match_name() {
407 return $this->match->match_name();
408 }
409
410 function type() {
411 if ( ( $this->action_type === 'url' || $this->action_type === 'error' || $this->action_type === 'random' ) && $this->action_code > 0 )
412 return $this->action_code;
413 else if ( $this->action_type === 'pass' )
414 return 'pass';
415 return '&mdash;';
416 }
417
418 public function get_id() {
419 return $this->id;
420 }
421
422 public function get_position() {
423 return $this->position;
424 }
425
426 public function get_group_id() {
427 return $this->group_id;
428 }
429
430 public function get_url() {
431 return $this->url;
432 }
433
434 public function get_title() {
435 return $this->title;
436 }
437
438 public function get_hits() {
439 return $this->last_count;
440 }
441
442 public function get_last_hit() {
443 return $this->last_access;
444 }
445
446 public function is_regex() {
447 return $this->regex ? true : false;
448 }
449
450 public function get_match_type() {
451 return $this->match_type;
452 }
453
454 public function get_action_type() {
455 return $this->action_type;
456 }
457
458 public function get_action_code() {
459 return intval( $this->action_code );
460 }
461
462 public function get_action_data() {
463 return $this->action_data;
464 }
465 }
466