PluginProbe
Redirection / 2.9
Redirection v2.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
← All changes | models/redirect.php +225 -200 4.02.9 View file →
@@ -1,16 +1,10 @@
1 1 <?php
2 2
3 -include_once dirname( __FILE__ ) . '/url.php';
4 -include_once dirname( __FILE__ ) . '/regex.php';
5 -include_once dirname( __FILE__ ) . '/redirect-sanitizer.php';
6 -
7 3 class Red_Item {
8 - private $id = null;
9 - private $url = null;
10 - private $match_url = null;
11 - private $match_data = null;
12 - private $regex = false;
4 + private $id = null;
5 + private $url = null;
6 + private $regex = false;
13 7 private $action_data = null;
14 8 private $action_code = 0;
15 9 private $action_type;
16 10 private $match_type;
@@ -16,81 +10,63 @@
16 10 private $match_type;
17 11 private $title;
18 12 private $last_access = null;
19 13 private $last_count = 0;
20 - private $status = 'enabled';
14 + private $status;
21 15 private $position;
22 16 private $group_id;
23 17
24 - public $source_flags = false;
25 -
26 - function __construct( $values = null ) {
18 + function __construct( $values, $type = '', $match = '' ) {
27 19 if ( is_object( $values ) ) {
28 20 $this->load_from_data( $values );
21 +
22 + if ( $this->last_access === '0000-00-00 00:00:00' ) {
23 + $this->last_access = 0;
24 + } else {
25 + $this->last_access = mysql2date( 'U', $this->last_access );
26 + }
29 27 }
30 28 }
31 29
32 30 private function load_from_data( stdClass $values ) {
33 31 foreach ( $values as $key => $value ) {
34 - if ( property_exists( $this, $key ) ) {
35 - $this->$key = $value;
36 - }
32 + $this->$key = $value;
37 33 }
38 34
39 - $this->regex = (bool) $this->regex;
40 - $this->last_access = $this->last_access === '0000-00-00 00:00:00' ? 0 : mysql2date( 'U', $this->last_access );
35 + if ( $this->match_type === '' ) {
36 + $this->match_type = 'url';
37 + }
41 38
42 - $this->load_matcher();
43 - $this->load_action();
44 - $this->load_source_flags();
45 - }
39 + $this->regex = (bool)$this->regex;
40 + $this->match = Red_Match::create( $this->match_type, $this->action_data );
41 + $this->match->id = $this->id;
42 + $this->match->action_code = $this->action_code;
46 43
47 - // v4 JSON
48 - private function load_source_flags() {
49 - // Default regex flag to regex column. This will be removed once the regex column has been migrated
50 - // todo: deprecate
51 - $this->source_flags = new Red_Source_Flags( array_merge( red_get_options(), [ 'flag_regex' => $this->regex ] ) );
44 + $action = false;
52 45
53 - if ( isset( $this->match_data ) ) {
54 - $json = json_decode( $this->match_data, true );
55 -
56 - if ( $json && isset( $json['source'] ) ) {
57 - // Merge redirect flags with default flags
58 - $this->source_flags->set_flags( array_merge( red_get_options(), $json['source'] ) );
59 - }
46 + if ( $this->action_type ) {
47 + $action = Red_Action::create( $this->action_type, $this->action_code );
60 48 }
61 - }
62 49
63 - private function load_matcher() {
64 - if ( empty( $this->match_type ) ) {
65 - $this->match_type = 'url';
50 + if ( $action ) {
51 + $this->action = $action;
52 + $this->match->action = $this->action;
66 53 }
67 -
68 - $this->match = Red_Match::create( $this->match_type, $this->action_data );
69 - }
70 -
71 - private function load_action() {
72 - if ( empty( $this->action_type ) ) {
73 - $this->action_type = 'nothing';
54 + else {
55 + $this->action = Red_Action::create( 'nothing', 0 );
74 56 }
75 -
76 - $this->action = Red_Action::create( $this->action_type, $this->action_code );
77 - $this->match->action = $this->action;
78 57 }
79 58
80 59 static function get_all_for_module( $module ) {
81 60 global $wpdb;
82 61
83 - $rows = $wpdb->get_results(
84 - $wpdb->prepare(
85 - "SELECT {$wpdb->prefix}redirection_items.* FROM {$wpdb->prefix}redirection_items
86 - INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id
87 - AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d
88 - WHERE {$wpdb->prefix}redirection_items.status='enabled'
89 - ORDER BY {$wpdb->prefix}redirection_groups.position,{$wpdb->prefix}redirection_items.position",
90 - $module
91 - )
92 - );
62 + $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.* FROM {$wpdb->prefix}redirection_items
63 + INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id
64 + AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d
65 + WHERE {$wpdb->prefix}redirection_items.status='enabled'
66 + ORDER BY {$wpdb->prefix}redirection_groups.position,{$wpdb->prefix}redirection_items.position", $module );
67 +
68 + $rows = $wpdb->get_results( $sql );
93 69 $items = array();
94 70
95 71 foreach ( (array) $rows as $row ) {
96 72 $items[] = new Red_Item( $row );
@@ -99,63 +75,25 @@
99 75 return $items;
100 76 }
101 77
102 78 static function get_for_url( $url ) {
103 - $status = new Red_Database_Status();
104 -
105 - // deprecate
106 - if ( $status->does_support( '4.0' ) ) {
107 - return self::get_for_matched_url( $url );
108 - }
109 -
110 - return self::get_old_url( $url );
111 - }
112 -
113 - static function get_for_matched_url( $url ) {
114 79 global $wpdb;
115 80
116 - $url = new Red_Url_Match( $url );
117 - $rows = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}redirection_items WHERE match_url=%s OR match_url='regex'", $url->get_url() ) );
81 + $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.position AS group_pos
82 + FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON
83 + {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled'
84 + AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE ({$wpdb->prefix}redirection_items.regex=1
85 + OR {$wpdb->prefix}redirection_items.url=%s)", WordPress_Module::MODULE_ID, $url );
118 86
87 + $rows = $wpdb->get_results( $sql );
119 88 $items = array();
120 89 if ( count( $rows ) > 0 ) {
121 90 foreach ( $rows as $row ) {
122 - $items[] = new Red_Item( $row );
91 + $items[] = array( 'position' => ( $row->group_pos * 1000 ) + $row->position, 'item' => new Red_Item( $row ) );
123 92 }
124 93 }
125 94
126 95 usort( $items, array( 'Red_Item', 'sort_urls' ) );
127 -
128 - return $items;
129 - }
130 -
131 - // deprecate
132 - public static function get_old_url( $url ) {
133 - global $wpdb;
134 -
135 - $rows = $wpdb->get_results(
136 - $wpdb->prepare(
137 - "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.position AS group_pos
138 - FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON
139 - {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled'
140 - AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE ({$wpdb->prefix}redirection_items.regex=1
141 - OR {$wpdb->prefix}redirection_items.url=%s)",
142 - WordPress_Module::MODULE_ID,
143 - $url
144 - )
145 - );
146 -
147 - $items = array();
148 - if ( count( $rows ) > 0 ) {
149 - foreach ( $rows as $row ) {
150 - $items[] = array(
151 - 'position' => ( $row->group_pos * 1000 ) + $row->position,
152 - 'item' => new Red_Item( $row ),
153 - );
154 - }
155 - }
156 -
157 - usort( $items, array( 'Red_Item', 'sort_urls' ) );
158 96 $items = array_map( array( 'Red_Item', 'reduce_sorted_items' ), $items );
159 97
160 98 // Sort it in PHP
161 99 ksort( $items );
@@ -162,13 +100,9 @@
162 100 $items = array_values( $items );
163 101 return $items;
164 102 }
165 103
166 - static public function reduce_sorted_items( $item ) {
167 - return $item['item'];
168 - }
169 -
170 - static public function get_all() {
104 + static function get_all() {
171 105 global $wpdb;
172 106
173 107 $rows = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}redirection_items" );
174 108 $items = array();
@@ -179,24 +113,26 @@
179 113
180 114 return $items;
181 115 }
182 116
183 - public static function sort_urls( $first, $second ) {
184 - if ( $first->position === $second->position ) {
117 + static function sort_urls( $first, $second ) {
118 + if ( $first['position'] === $second['position'] ) {
185 119 return 0;
186 120 }
187 121
188 - return ( $first->position < $second->position ) ? -1 : 1;
122 + return ($first['position'] < $second['position']) ? -1 : 1;
189 123 }
190 124
125 + static function reduce_sorted_items( $item ) {
126 + return $item['item'];
127 + }
128 +
191 129 static function get_by_id( $id ) {
192 130 global $wpdb;
193 131
194 132 $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}redirection_items WHERE id=%d", $id ) );
195 - if ( $row ) {
133 + if ( $row )
196 134 return new Red_Item( $row );
197 - }
198 -
199 135 return false;
200 136 }
201 137
202 138 public static function disable_where_matches( $url ) {
@@ -201,9 +137,9 @@
201 137
202 138 public static function disable_where_matches( $url ) {
203 139 global $wpdb;
204 140
205 - $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'status' => 'disabled' ), array( 'url' => $url ) );
141 + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => 'disabled' ), array( 'url' => $url ) );
206 142 }
207 143
208 144 public function delete() {
209 145 global $wpdb;
@@ -208,9 +144,8 @@
208 144 public function delete() {
209 145 global $wpdb;
210 146
211 147 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_items WHERE id=%d", $this->id ) );
212 - do_action( 'redirection_redirect_deleted', $this );
213 148
214 149 Red_Module::flush( $this->group_id );
215 150 }
216 151
@@ -222,33 +157,16 @@
222 157 if ( is_wp_error( $data ) ) {
223 158 return $data;
224 159 }
225 160
226 - $data['status'] = 'enabled';
227 -
228 - // todo: fix this mess
229 - if ( ( isset( $details['enabled'] ) && ( $details['enabled'] === 'disabled' || $details['enabled'] === false ) ) || ( isset( $details['status'] ) && $details['status'] === 'disabled' ) ) {
230 - $data['status'] = 'disabled';
231 - }
232 -
233 - if ( ! isset( $details['position'] ) || $details['position'] === 0 ) {
234 - $data['position'] = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $data['group_id'] ) );
235 - }
236 -
161 + $data['status'] = isset( $details['status'] ) && $details['status'] === 'disabled' ? 'disabled' : 'enabled';
162 + $data['position'] = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $data['group_id'] ) );
237 163 $data = apply_filters( 'redirection_create_redirect', $data );
238 164
239 - if ( ! empty( $data['match_data'] ) ) {
240 - $data['match_data'] = json_encode( $data['match_data'] );
241 - }
242 -
243 165 // Create
244 - if ( $wpdb->insert( $wpdb->prefix . 'redirection_items', $data ) !== false ) {
166 + if ( $wpdb->insert( $wpdb->prefix.'redirection_items', $data ) !== false ) {
245 167 Red_Module::flush( $data['group_id'] );
246 -
247 - $redirect = self::get_by_id( $wpdb->insert_id );
248 - do_action( 'redirection_redirect_updated', $wpdb->insert_id, $redirect );
249 -
250 - return $redirect;
168 + return self::get_by_id( $wpdb->insert_id );
251 169 }
252 170
253 171 return new WP_Error( 'redirect', __( 'Unable to add new redirect' ) );
254 172 }
@@ -268,16 +186,10 @@
268 186 $old_group = $this->group_id;
269 187 }
270 188
271 189 // Save this
272 - $data = apply_filters( 'redirection_update_redirect', $data );
273 - if ( ! empty( $data['match_data'] ) ) {
274 - $data['match_data'] = json_encode( $data['match_data'] );
275 - }
190 + $wpdb->update( $wpdb->prefix.'redirection_items', $data, array( 'id' => $this->id ) );
276 191
277 - $wpdb->update( $wpdb->prefix . 'redirection_items', $data, array( 'id' => $this->id ) );
278 - do_action( 'redirection_redirect_updated', $this, self::get_by_id( $this->id ) );
279 -
280 192 $this->load_from_data( (object) $data );
281 193
282 194 Red_Module::flush( $this->group_id );
283 195
@@ -287,31 +199,29 @@
287 199
288 200 return true;
289 201 }
290 202
291 - /**
292 - * Determine if a requested URL matches this URL
293 - *
294 - * @param string $requested_url
295 - * @return bool true if matched, false otherwise
296 - */
297 - public function matches( $requested_url ) {
203 + public function matches( $url ) {
298 204 if ( ! $this->is_enabled() ) {
299 205 return false;
300 206 }
301 207
302 - $url = new Red_Url( $this->url );
303 - if ( $url->is_match( $requested_url, $this->source_flags ) ) {
208 + $this->url = str_replace( ' ', '%20', $this->url );
209 + $matches = false;
210 +
211 + // Check if we match the URL
212 + 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 213 // Check if our match wants this URL
305 - $target = $this->match->get_target( $requested_url, $url->get_url(), $this->source_flags );
306 - $target = Red_Url_Query::add_to_target( $target, $requested_url, $this->source_flags );
214 + $target = $this->match->get_target( $url, $this->url, $this->regex );
307 215 $target = apply_filters( 'redirection_url_target', $target, $this->url );
308 216 $target = $this->action->process_before( $this->action_code, $target );
309 217
310 218 if ( $target ) {
311 - do_action( 'redirection_visit', $this, $requested_url, $target );
219 + do_action( 'redirection_visit', $this, $url, $target );
312 220 return $this->action->process_after( $this->action_code, $target );
313 221 }
222 +
223 + return true;
314 224 }
315 225
316 226 return false;
317 227 }
@@ -325,14 +235,9 @@
325 235 $this->last_count++;
326 236 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}redirection_items SET last_count=last_count+1, last_access=NOW() WHERE id=%d", $this->id ) );
327 237
328 238 if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] !== -1 && $target ) {
329 - $details = array(
330 - 'redirect_id' => $this->id,
331 - 'group_id' => $this->group_id,
332 - );
333 -
334 - RE_Log::create( $url, $target, Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer(), $details );
239 + RE_Log::create( $url, $target, Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer(), array( 'redirect_id' => $this->id, 'group_id' => $this->group_id ) );
335 240 }
336 241 }
337 242
338 243 public function is_enabled() {
@@ -344,17 +249,9 @@
344 249
345 250 $this->last_count = 0;
346 251 $this->last_access = '0000-00-00 00:00:00';
347 252
348 - $update = array(
349 - 'last_count' => 0,
350 - 'last_access' => $this->last_access,
351 - );
352 - $where = array(
353 - 'id' => $this->id,
354 - );
355 -
356 - $wpdb->update( $wpdb->prefix . 'redirection_items', $update, $where );
253 + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'last_count' => 0, 'last_access' => $this->last_access ), array( 'id' => $this->id ) );
357 254 }
358 255
359 256 public function enable() {
360 257 global $wpdb;
@@ -359,9 +256,9 @@
359 256 public function enable() {
360 257 global $wpdb;
361 258
362 259 $this->status = 'enabled';
363 - $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
260 + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
364 261 }
365 262
366 263 public function disable() {
367 264 global $wpdb;
@@ -366,9 +263,9 @@
366 263 public function disable() {
367 264 global $wpdb;
368 265
369 266 $this->status = 'disabled';
370 - $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
267 + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
371 268 }
372 269
373 270 public function get_id() {
374 271 return intval( $this->id, 10 );
@@ -385,22 +282,8 @@
385 282 public function get_url() {
386 283 return $this->url;
387 284 }
388 285
389 - public function get_match_url() {
390 - return $this->match_url;
391 - }
392 -
393 - public function get_match_data() {
394 - $source = $this->source_flags->get_json_with_defaults();
395 -
396 - if ( ! empty( $source ) ) {
397 - return [ 'source' => $source ];
398 - }
399 -
400 - return null;
401 - }
402 -
403 286 public function get_title() {
404 287 return $this->title ? $this->title : '';
405 288 }
406 289
@@ -440,10 +323,10 @@
440 323 $limit = RED_DEFAULT_PER_PAGE;
441 324 $offset = 0;
442 325 $where = '';
443 326
444 - if ( isset( $params['orderby'] ) && in_array( $params['orderby'], array( 'url', 'last_count', 'last_access', 'position' ), true ) ) {
445 - $orderby = $params['orderby'];
327 + if ( isset( $params['orderBy'] ) && in_array( $params['orderBy'], array( 'url', 'last_count', 'last_access', 'position' ), true ) ) {
328 + $orderby = $params['orderBy'];
446 329 }
447 330
448 331 if ( isset( $params['direction'] ) && in_array( $params['direction'], array( 'asc', 'desc' ), true ) ) {
449 332 $direction = strtoupper( $params['direction'] );
@@ -450,16 +333,16 @@
450 333 }
451 334
452 335 if ( isset( $params['filter'] ) && strlen( $params['filter'] ) > 0 && $params['filter'] !== '0' ) {
453 336 if ( isset( $params['filterBy'] ) && $params['filterBy'] === 'group' ) {
454 - $where = $wpdb->prepare( 'WHERE group_id=%d', intval( $params['filter'], 10 ) );
337 + $where = $wpdb->prepare( "WHERE group_id=%d", intval( $params['filter'], 10 ) );
455 338 } else {
456 - $where = $wpdb->prepare( 'WHERE url LIKE %s', '%' . $wpdb->esc_like( trim( $params['filter'] ) ) . '%' );
339 + $where = $wpdb->prepare( 'WHERE url LIKE %s', '%'.$wpdb->esc_like( trim( $params['filter'] ) ).'%' );
457 340 }
458 341 }
459 342
460 - if ( isset( $params['per_page'] ) ) {
461 - $limit = intval( $params['per_page'], 10 );
343 + if ( isset( $params['perPage'] ) ) {
344 + $limit = intval( $params['perPage'], 10 );
462 345 $limit = min( RED_MAX_PER_PAGE, $limit );
463 346 $limit = max( 5, $limit );
464 347 }
465 348
@@ -468,13 +351,13 @@
468 351 $offset = max( 0, $offset );
469 352 $offset *= $limit;
470 353 }
471 354
472 - // $orderby and $direction is whitelisted
473 - $rows = $wpdb->get_results(
474 - "SELECT * FROM {$wpdb->prefix}redirection_items $where ORDER BY $orderby $direction " . $wpdb->prepare( 'LIMIT %d,%d', $offset, $limit )
475 - );
476 - $total_items = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items " . $where ) );
355 + $table = $wpdb->prefix.'redirection_items';
356 + $sql = trim( "SELECT * FROM {$table} $where " ).$wpdb->prepare( " ORDER BY $orderby $direction LIMIT %d,%d", $offset, $limit );
357 +
358 + $rows = $wpdb->get_results( $sql );
359 + $total_items = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$table} ".$where ) );
477 360 $items = array();
478 361
479 362 foreach ( $rows as $row ) {
480 363 $group = new Red_Item( $row );
@@ -490,10 +373,8 @@
490 373 public function to_json() {
491 374 return array(
492 375 'id' => $this->get_id(),
493 376 'url' => $this->get_url(),
494 - 'match_url' => $this->get_match_url(),
495 - 'match_data' => $this->get_match_data(),
496 377 'action_code' => $this->get_action_code(),
497 378 'action_type' => $this->get_action_type(),
498 379 'action_data' => $this->match->get_data(),
499 380 'match_type' => $this->get_match_type(),
@@ -504,6 +385,150 @@
504 385 'position' => $this->get_position(),
505 386 'last_access' => $this->get_last_hit() > 0 ? date_i18n( get_option( 'date_format' ), $this->get_last_hit() ) : '-',
506 387 'enabled' => $this->is_enabled(),
507 388 );
389 + }
390 +}
391 +
392 +class Red_Item_Sanitize {
393 + private function clean_array( $array ) {
394 + foreach ( $array as $name => $value ) {
395 + if ( is_array( $value ) ) {
396 + $array[ $name ] = $this->clean_array( $value );
397 + } else {
398 + $value = stripslashes( $value );
399 + $value = trim( $value );
400 + $array[ $name ] = $value;
401 + }
402 + };
403 +
404 + return $array;
405 + }
406 +
407 + public function get( array $details ) {
408 + $data = array();
409 + $details = $this->clean_array( $details );
410 +
411 + $data['regex'] = isset( $details['regex'] ) && intval( $details['regex'], 10 ) === 1 ? 1 : 0;
412 + $data['title'] = isset( $details['title'] ) ? $details['title'] : null;
413 + $data['url'] = $this->get_url( empty( $details['url'] ) ? $this->auto_generate() : $details['url'], $data['regex'] );
414 + $data['group_id'] = $this->get_group( isset( $details['group_id'] ) ? $details['group_id'] : 0 );
415 + $data['position'] = $this->get_position( $details );
416 +
417 + if ( $data['title'] ) {
418 + $data['title'] = substr( $data['title'], 0, 50 );
419 + }
420 +
421 + $matcher = Red_Match::create( isset( $details['match_type'] ) ? $details['match_type'] : false );
422 + if ( ! $matcher ) {
423 + return new WP_Error( 'redirect', __( 'Invalid redirect matcher', 'redirection' ) );
424 + }
425 +
426 + $action_code = isset( $details['action_code'] ) ? intval( $details['action_code'], 10 ) : 0;
427 + $action = Red_Action::create( isset( $details['action_type'] ) ? $details['action_type'] : false, $action_code );
428 + if ( ! $action ) {
429 + return new WP_Error( 'redirect', __( 'Invalid redirect action', 'redirection' ) );
430 + }
431 +
432 + $data['action_type'] = $details['action_type'];
433 + $data['action_code'] = $this->get_code( $details['action_type'], $action_code );
434 + $data['match_type'] = $details['match_type'];
435 +
436 + if ( isset( $details['action_data'] ) ) {
437 + $match_data = $matcher->save( $details['action_data'], ! $this->is_url_type( $data['action_type'] ) );
438 + $data['action_data'] = is_array( $match_data ) ? serialize( $match_data ) : $match_data;
439 + }
440 +
441 + // Any errors?
442 + foreach ( $data as $value ) {
443 + if ( is_wp_error( $value ) ) {
444 + return $value;
445 + }
446 + }
447 +
448 + return apply_filters( 'redirection_validate_redirect', $data );
449 + }
450 +
451 + protected function get_position( $details ) {
452 + if ( isset( $details['position'] ) ) {
453 + return max( 0, intval( $details['position'], 10 ) );
454 + }
455 +
456 + return 0;
457 + }
458 +
459 + protected function is_url_type( $type ) {
460 + if ( $type === 'url' || $type === 'pass' ) {
461 + return true;
462 + }
463 +
464 + return false;
465 + }
466 +
467 + protected function get_code( $action_type, $code ) {
468 + if ( $action_type === 'url' || $action_type === 'random' ) {
469 + if ( in_array( $code, array( 301, 302, 307, 308 ), true ) ) {
470 + return $code;
471 + }
472 + }
473 +
474 + if ( $action_type === 'error' ) {
475 + if ( in_array( $code, array( 401, 404, 410 ), true ) ) {
476 + return $code;
477 + }
478 + }
479 +
480 + return 0;
481 + }
482 +
483 + protected function get_group( $group_id ) {
484 + $group_id = intval( $group_id, 10 );
485 +
486 + if ( ! Red_Group::get( $group_id ) ) {
487 + return new WP_Error( 'redirect', __( 'Invalid group when creating redirect', 'redirection' ) );
488 + }
489 +
490 + return $group_id;
491 + }
492 +
493 + protected function get_url( $url, $regex ) {
494 + $url = self::sanitize_url( $url, $regex );
495 +
496 + if ( $url === '' ) {
497 + return new WP_Error( 'redirect', __( 'Invalid source URL', 'redirection' ) );
498 + }
499 +
500 + return $url;
501 + }
502 +
503 + protected function auto_generate() {
504 + $options = red_get_options();
505 + $url = '';
506 +
507 + if ( isset( $options['auto_target'] ) && $options['auto_target'] ) {
508 + $id = time();
509 + $url = str_replace( '$dec$', $id, $options['auto_target'] );
510 + $url = str_replace( '$hex$', sprintf( '%x', $id ), $url );
511 + }
512 +
513 + return $url;
514 + }
515 +
516 + public function sanitize_url( $url, $regex = false ) {
517 + // Make sure that the old URL is relative
518 + $url = preg_replace( '@^https?://(.*?)/@', '/', $url );
519 + $url = preg_replace( '@^https?://(.*?)$@', '/', $url );
520 +
521 + // No new lines
522 + $url = preg_replace( "/[\r\n\t].*?$/s", '', $url );
523 +
524 + // Clean control codes
525 + $url = preg_replace( '/[^\PC\s]/u', '', $url );
526 +
527 + // Ensure a slash at start
528 + if ( substr( $url, 0, 1 ) !== '/' && $regex === false ) {
529 + $url = '/'.$url;
530 + }
531 +
532 + return $url;
508 533 }
509 534 }