| @@ -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_old' ) ); | |
| 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,22 +113,18 @@ | ||
| 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 | |
| 191 | - public static function sort_urls_old( $first, $second ) { | |
| 192 | - if ( $first['position'] === $second['position'] ) { | |
| 193 | - return 0; | |
| 194 | - } | |
| 195 | - | |
| 196 | - return ( $first['position'] < $second['position'] ) ? -1 : 1; | |
| 125 | + static function reduce_sorted_items( $item ) { | |
| 126 | + return $item['item']; | |
| 197 | 127 | } |
| 198 | 128 | |
| 199 | 129 | static function get_by_id( $id ) { |
| 200 | 130 | global $wpdb; |
| @@ -199,12 +129,10 @@ | ||
| 199 | 129 | static function get_by_id( $id ) { |
| 200 | 130 | global $wpdb; |
| 201 | 131 | |
| 202 | 132 | $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}redirection_items WHERE id=%d", $id ) ); |
| 203 | - if ( $row ) { | |
| 133 | + if ( $row ) | |
| 204 | 134 | return new Red_Item( $row ); |
| 205 | - } | |
| 206 | - | |
| 207 | 135 | return false; |
| 208 | 136 | } |
| 209 | 137 | |
| 210 | 138 | public static function disable_where_matches( $url ) { |
| @@ -209,9 +137,9 @@ | ||
| 209 | 137 | |
| 210 | 138 | public static function disable_where_matches( $url ) { |
| 211 | 139 | global $wpdb; |
| 212 | 140 | |
| 213 | - $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 ) ); | |
| 214 | 142 | } |
| 215 | 143 | |
| 216 | 144 | public function delete() { |
| 217 | 145 | global $wpdb; |
| @@ -216,9 +144,8 @@ | ||
| 216 | 144 | public function delete() { |
| 217 | 145 | global $wpdb; |
| 218 | 146 | |
| 219 | 147 | $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_items WHERE id=%d", $this->id ) ); |
| 220 | - do_action( 'redirection_redirect_deleted', $this ); | |
| 221 | 148 | |
| 222 | 149 | Red_Module::flush( $this->group_id ); |
| 223 | 150 | } |
| 224 | 151 | |
| @@ -231,32 +158,15 @@ | ||
| 231 | 158 | return $data; |
| 232 | 159 | } |
| 233 | 160 | |
| 234 | 161 | $data['status'] = 'enabled'; |
| 235 | - | |
| 236 | - // todo: fix this mess | |
| 237 | - if ( ( isset( $details['enabled'] ) && ( $details['enabled'] === 'disabled' || $details['enabled'] === false ) ) || ( isset( $details['status'] ) && $details['status'] === 'disabled' ) ) { | |
| 238 | - $data['status'] = 'disabled'; | |
| 239 | - } | |
| 240 | - | |
| 241 | - if ( ! isset( $details['position'] ) || $details['position'] === 0 ) { | |
| 242 | - $data['position'] = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $data['group_id'] ) ); | |
| 243 | - } | |
| 244 | - | |
| 162 | + $data['position'] = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $data['group_id'] ) ); | |
| 245 | 163 | $data = apply_filters( 'redirection_create_redirect', $data ); |
| 246 | 164 | |
| 247 | - if ( ! empty( $data['match_data'] ) ) { | |
| 248 | - $data['match_data'] = json_encode( $data['match_data'] ); | |
| 249 | - } | |
| 250 | - | |
| 251 | 165 | // Create |
| 252 | - if ( $wpdb->insert( $wpdb->prefix . 'redirection_items', $data ) !== false ) { | |
| 166 | + if ( $wpdb->insert( $wpdb->prefix.'redirection_items', $data ) ) { | |
| 253 | 167 | Red_Module::flush( $data['group_id'] ); |
| 254 | - | |
| 255 | - $redirect = self::get_by_id( $wpdb->insert_id ); | |
| 256 | - do_action( 'redirection_redirect_updated', $wpdb->insert_id, $redirect ); | |
| 257 | - | |
| 258 | - return $redirect; | |
| 168 | + return self::get_by_id( $wpdb->insert_id ); | |
| 259 | 169 | } |
| 260 | 170 | |
| 261 | 171 | return new WP_Error( 'redirect', __( 'Unable to add new redirect' ) ); |
| 262 | 172 | } |
| @@ -276,64 +186,35 @@ | ||
| 276 | 186 | $old_group = $this->group_id; |
| 277 | 187 | } |
| 278 | 188 | |
| 279 | 189 | // Save this |
| 280 | - $data = apply_filters( 'redirection_update_redirect', $data ); | |
| 281 | - if ( ! empty( $data['match_data'] ) ) { | |
| 282 | - $data['match_data'] = json_encode( $data['match_data'] ); | |
| 283 | - } | |
| 190 | + $wpdb->update( $wpdb->prefix.'redirection_items', $data, array( 'id' => $this->id ) ); | |
| 284 | 191 | |
| 285 | - $result = $wpdb->update( $wpdb->prefix . 'redirection_items', $data, array( 'id' => $this->id ) ); | |
| 286 | - if ( $result !== false ) { | |
| 287 | - do_action( 'redirection_redirect_updated', $this, self::get_by_id( $this->id ) ); | |
| 288 | - $this->load_from_data( (object) $data ); | |
| 192 | + $this->load_from_data( (object) $data ); | |
| 289 | 193 | |
| 290 | - Red_Module::flush( $this->group_id ); | |
| 194 | + Red_Module::flush( $this->group_id ); | |
| 291 | 195 | |
| 292 | - if ( $old_group !== $this->group_id ) { | |
| 293 | - Red_Module::flush( $old_group ); | |
| 294 | - } | |
| 295 | - | |
| 296 | - return true; | |
| 196 | + if ( $old_group !== $this->group_id ) { | |
| 197 | + Red_Module::flush( $old_group ); | |
| 297 | 198 | } |
| 298 | 199 | |
| 299 | - return new WP_Error( 'redirect', __( 'Unable to update redirect' ) ); | |
| 200 | + return true; | |
| 300 | 201 | } |
| 301 | 202 | |
| 302 | - /** | |
| 303 | - * Determine if a requested URL matches this URL | |
| 304 | - * | |
| 305 | - * @param string $requested_url | |
| 306 | - * @return bool true if matched, false otherwise | |
| 307 | - */ | |
| 308 | - public function matches( $requested_url ) { | |
| 309 | - if ( ! $this->is_enabled() ) { | |
| 310 | - return false; | |
| 311 | - } | |
| 203 | + public function matches( $url ) { | |
| 204 | + $this->url = str_replace( ' ', '%20', $this->url ); | |
| 205 | + $matches = false; | |
| 312 | 206 | |
| 313 | - $url = new Red_Url( $this->url ); | |
| 314 | - if ( $url->is_match( $requested_url, $this->source_flags ) ) { | |
| 315 | - // URL is matched, now match the redirect type (i.e. login status, IP address) | |
| 316 | - $target = $this->match->is_match( $requested_url ); | |
| 207 | + // Check if we match the URL | |
| 208 | + 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) ) { | |
| 209 | + // Check if our match wants this URL | |
| 210 | + $target = $this->match->get_target( $url, $this->url, $this->regex ); | |
| 211 | + $target = apply_filters( 'redirection_url_target', $target, $this->url ); | |
| 317 | 212 | |
| 318 | - // Check if our action wants a URL | |
| 319 | - if ( $this->action->needs_target() ) { | |
| 320 | - // Our action requires a target URL - get this, using our type match result | |
| 321 | - $target = $this->match->get_target_url( $requested_url, $url->get_url(), $this->source_flags, $target ); | |
| 322 | - $target = Red_Url_Query::add_to_target( $target, $requested_url, $this->source_flags ); | |
| 323 | - $target = apply_filters( 'redirection_url_target', $target, $this->url ); | |
| 213 | + if ( $target && $this->is_enabled() ) { | |
| 214 | + $this->visit( $url, $target ); | |
| 215 | + return $this->action->process_before( $this->action_code, $target ); | |
| 324 | 216 | } |
| 325 | - | |
| 326 | - // Fire any early actions | |
| 327 | - if ( $target ) { | |
| 328 | - $target = $this->action->process_before( $this->action_code, $target ); | |
| 329 | - } | |
| 330 | - | |
| 331 | - if ( $target ) { | |
| 332 | - // We still have a target, so log it and carry on with the action | |
| 333 | - do_action( 'redirection_visit', $this, $requested_url, $target ); | |
| 334 | - return $this->action->process_after( $this->action_code, $target ); | |
| 335 | - } | |
| 336 | 217 | } |
| 337 | 218 | |
| 338 | 219 | return false; |
| 339 | 220 | } |
| @@ -346,15 +227,10 @@ | ||
| 346 | 227 | // Update the counters |
| 347 | 228 | $this->last_count++; |
| 348 | 229 | $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}redirection_items SET last_count=last_count+1, last_access=NOW() WHERE id=%d", $this->id ) ); |
| 349 | 230 | |
| 350 | - if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] !== -1 && $target ) { | |
| 351 | - $details = array( | |
| 352 | - 'redirect_id' => $this->id, | |
| 353 | - 'group_id' => $this->group_id, | |
| 354 | - ); | |
| 355 | - | |
| 356 | - RE_Log::create( $url, $target, Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer(), $details ); | |
| 231 | + if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] > 0 ) { | |
| 232 | + $log = 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 ) ); | |
| 357 | 233 | } |
| 358 | 234 | } |
| 359 | 235 | |
| 360 | 236 | public function is_enabled() { |
| @@ -366,17 +242,9 @@ | ||
| 366 | 242 | |
| 367 | 243 | $this->last_count = 0; |
| 368 | 244 | $this->last_access = '0000-00-00 00:00:00'; |
| 369 | 245 | |
| 370 | - $update = array( | |
| 371 | - 'last_count' => 0, | |
| 372 | - 'last_access' => $this->last_access, | |
| 373 | - ); | |
| 374 | - $where = array( | |
| 375 | - 'id' => $this->id, | |
| 376 | - ); | |
| 377 | - | |
| 378 | - $wpdb->update( $wpdb->prefix . 'redirection_items', $update, $where ); | |
| 246 | + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'last_count' => 0, 'last_access' => $this->last_access ), array( 'id' => $this->id ) ); | |
| 379 | 247 | } |
| 380 | 248 | |
| 381 | 249 | public function enable() { |
| 382 | 250 | global $wpdb; |
| @@ -381,9 +249,9 @@ | ||
| 381 | 249 | public function enable() { |
| 382 | 250 | global $wpdb; |
| 383 | 251 | |
| 384 | 252 | $this->status = 'enabled'; |
| 385 | - $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) ); | |
| 253 | + $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) ); | |
| 386 | 254 | } |
| 387 | 255 | |
| 388 | 256 | public function disable() { |
| 389 | 257 | global $wpdb; |
| @@ -388,9 +256,9 @@ | ||
| 388 | 256 | public function disable() { |
| 389 | 257 | global $wpdb; |
| 390 | 258 | |
| 391 | 259 | $this->status = 'disabled'; |
| 392 | - $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 ) ); | |
| 393 | 261 | } |
| 394 | 262 | |
| 395 | 263 | public function get_id() { |
| 396 | 264 | return intval( $this->id, 10 ); |
| @@ -407,22 +275,8 @@ | ||
| 407 | 275 | public function get_url() { |
| 408 | 276 | return $this->url; |
| 409 | 277 | } |
| 410 | 278 | |
| 411 | - public function get_match_url() { | |
| 412 | - return $this->match_url; | |
| 413 | - } | |
| 414 | - | |
| 415 | - public function get_match_data() { | |
| 416 | - $source = $this->source_flags->get_json_with_defaults(); | |
| 417 | - | |
| 418 | - if ( ! empty( $source ) ) { | |
| 419 | - return [ 'source' => $source ]; | |
| 420 | - } | |
| 421 | - | |
| 422 | - return null; | |
| 423 | - } | |
| 424 | - | |
| 425 | 279 | public function get_title() { |
| 426 | 280 | return $this->title ? $this->title : ''; |
| 427 | 281 | } |
| 428 | 282 | |
| @@ -462,10 +316,10 @@ | ||
| 462 | 316 | $limit = RED_DEFAULT_PER_PAGE; |
| 463 | 317 | $offset = 0; |
| 464 | 318 | $where = ''; |
| 465 | 319 | |
| 466 | - if ( isset( $params['orderby'] ) && in_array( $params['orderby'], array( 'url', 'last_count', 'last_access', 'position' ), true ) ) { | |
| 467 | - $orderby = $params['orderby']; | |
| 320 | + if ( isset( $params['orderBy'] ) && in_array( $params['orderBy'], array( 'url', 'last_count', 'last_access', 'position' ), true ) ) { | |
| 321 | + $orderby = $params['orderBy']; | |
| 468 | 322 | } |
| 469 | 323 | |
| 470 | 324 | if ( isset( $params['direction'] ) && in_array( $params['direction'], array( 'asc', 'desc' ), true ) ) { |
| 471 | 325 | $direction = strtoupper( $params['direction'] ); |
| @@ -470,19 +324,19 @@ | ||
| 470 | 324 | if ( isset( $params['direction'] ) && in_array( $params['direction'], array( 'asc', 'desc' ), true ) ) { |
| 471 | 325 | $direction = strtoupper( $params['direction'] ); |
| 472 | 326 | } |
| 473 | 327 | |
| 474 | - if ( isset( $params['filter'] ) && strlen( $params['filter'] ) > 0 && $params['filter'] !== '0' ) { | |
| 328 | + if ( isset( $params['filter'] ) && strlen( $params['filter'] ) > 0 ) { | |
| 475 | 329 | if ( isset( $params['filterBy'] ) && $params['filterBy'] === 'group' ) { |
| 476 | - $where = $wpdb->prepare( 'WHERE group_id=%d', intval( $params['filter'], 10 ) ); | |
| 330 | + $where = $wpdb->prepare( "WHERE group_id=%d", intval( $params['filter'], 10 ) ); | |
| 477 | 331 | } else { |
| 478 | - $where = $wpdb->prepare( 'WHERE url LIKE %s', '%' . $wpdb->esc_like( trim( $params['filter'] ) ) . '%' ); | |
| 332 | + $where = $wpdb->prepare( 'WHERE url LIKE %s', '%'.$wpdb->esc_like( trim( $params['filter'] ) ).'%' ); | |
| 479 | 333 | } |
| 480 | 334 | } |
| 481 | 335 | |
| 482 | - if ( isset( $params['per_page'] ) ) { | |
| 483 | - $limit = intval( $params['per_page'], 10 ); | |
| 484 | - $limit = min( RED_MAX_PER_PAGE, $limit ); | |
| 336 | + if ( isset( $params['perPage'] ) ) { | |
| 337 | + $limit = intval( $params['perPage'], 10 ); | |
| 338 | + $limit = min( 100, $limit ); | |
| 485 | 339 | $limit = max( 5, $limit ); |
| 486 | 340 | } |
| 487 | 341 | |
| 488 | 342 | if ( isset( $params['page'] ) ) { |
| @@ -490,13 +344,13 @@ | ||
| 490 | 344 | $offset = max( 0, $offset ); |
| 491 | 345 | $offset *= $limit; |
| 492 | 346 | } |
| 493 | 347 | |
| 494 | - // $orderby and $direction is whitelisted | |
| 495 | - $rows = $wpdb->get_results( | |
| 496 | - "SELECT * FROM {$wpdb->prefix}redirection_items $where ORDER BY $orderby $direction " . $wpdb->prepare( 'LIMIT %d,%d', $offset, $limit ) | |
| 497 | - ); | |
| 498 | - $total_items = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items " . $where ) ); | |
| 348 | + $table = $wpdb->prefix.'redirection_items'; | |
| 349 | + $sql = trim( "SELECT * FROM {$table} $where " ).$wpdb->prepare( " ORDER BY $orderby $direction LIMIT %d,%d", $offset, $limit ); | |
| 350 | + | |
| 351 | + $rows = $wpdb->get_results( $sql ); | |
| 352 | + $total_items = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$table} ".$where ) ); | |
| 499 | 353 | $items = array(); |
| 500 | 354 | |
| 501 | 355 | foreach ( $rows as $row ) { |
| 502 | 356 | $group = new Red_Item( $row ); |
| @@ -512,13 +366,11 @@ | ||
| 512 | 366 | public function to_json() { |
| 513 | 367 | return array( |
| 514 | 368 | 'id' => $this->get_id(), |
| 515 | 369 | 'url' => $this->get_url(), |
| 516 | - 'match_url' => $this->get_match_url(), | |
| 517 | - 'match_data' => $this->get_match_data(), | |
| 518 | 370 | 'action_code' => $this->get_action_code(), |
| 519 | 371 | 'action_type' => $this->get_action_type(), |
| 520 | - 'action_data' => $this->match->get_data(), | |
| 372 | + 'action_data' => maybe_unserialize( $this->get_action_data() ), | |
| 521 | 373 | 'match_type' => $this->get_match_type(), |
| 522 | 374 | 'title' => $this->get_title(), |
| 523 | 375 | 'hits' => $this->get_hits(), |
| 524 | 376 | 'regex' => $this->is_regex(), |
| @@ -526,6 +378,136 @@ | ||
| 526 | 378 | 'position' => $this->get_position(), |
| 527 | 379 | 'last_access' => $this->get_last_hit() > 0 ? date_i18n( get_option( 'date_format' ), $this->get_last_hit() ) : '-', |
| 528 | 380 | 'enabled' => $this->is_enabled(), |
| 529 | 381 | ); |
| 382 | + } | |
| 383 | +} | |
| 384 | + | |
| 385 | +class Red_Item_Sanitize { | |
| 386 | + public function get( array $details ) { | |
| 387 | + $data = array(); | |
| 388 | + | |
| 389 | + $details = array_map( 'trim', $details ); | |
| 390 | + $details = array_map( 'stripslashes', $details ); | |
| 391 | + | |
| 392 | + $data['regex'] = isset( $details['regex'] ) && ( $details['regex'] === 'true' || $details['regex'] === '1' ) ? 1 : 0; | |
| 393 | + $data['title'] = isset( $details['title'] ) ? $details['title'] : null; | |
| 394 | + $data['url'] = $this->get_url( empty( $details['url'] ) ? $this->auto_generate() : $details['url'], $data['regex'] ); | |
| 395 | + $data['group_id'] = $this->get_group( isset( $details['group_id'] ) ? $details['group_id'] : 0 ); | |
| 396 | + $data['position'] = $this->get_position( $details ); | |
| 397 | + | |
| 398 | + $matcher = Red_Match::create( isset( $details['match_type'] ) ? $details['match_type'] : false ); | |
| 399 | + if ( ! $matcher ) { | |
| 400 | + return new WP_Error( 'redirect', __( 'Invalid redirect matcher', 'redirection' ) ); | |
| 401 | + } | |
| 402 | + | |
| 403 | + $action_code = isset( $details['action_code'] ) ? intval( $details['action_code'], 10 ) : 0; | |
| 404 | + $action = Red_Action::create( isset( $details['action_type'] ) ? $details['action_type'] : false, $action_code ); | |
| 405 | + if ( ! $action ) { | |
| 406 | + return new WP_Error( 'redirect', __( 'Invalid redirect action', 'redirection' ) ); | |
| 407 | + } | |
| 408 | + | |
| 409 | + $data['action_type'] = $details['action_type']; | |
| 410 | + $data['action_code'] = $this->get_code( $details['action_type'], $action_code ); | |
| 411 | + $data['match_type'] = $details['match_type']; | |
| 412 | + | |
| 413 | + $match_data = $matcher->save( $details, ! $this->is_url_type( $data['action_type'] ) ); | |
| 414 | + | |
| 415 | + $data['action_data'] = is_array( $match_data ) ? serialize( $match_data ) : $match_data; | |
| 416 | + | |
| 417 | + // Any errors? | |
| 418 | + foreach ( $data as $value ) { | |
| 419 | + if ( is_wp_error( $value ) ) { | |
| 420 | + return $value; | |
| 421 | + } | |
| 422 | + } | |
| 423 | + | |
| 424 | + return apply_filters( 'redirection_validate_redirect', $data ); | |
| 425 | + } | |
| 426 | + | |
| 427 | + protected function get_position( $details ) { | |
| 428 | + if ( isset( $details['position'] ) ) { | |
| 429 | + return max( 0, intval( $details['position'], 10 ) ); | |
| 430 | + } | |
| 431 | + | |
| 432 | + return 0; | |
| 433 | + } | |
| 434 | + | |
| 435 | + protected function is_url_type( $type ) { | |
| 436 | + if ( $type === 'url' || $type === 'pass' ) { | |
| 437 | + return true; | |
| 438 | + } | |
| 439 | + | |
| 440 | + return false; | |
| 441 | + } | |
| 442 | + | |
| 443 | + protected function get_code( $action_type, $code ) { | |
| 444 | + if ( $action_type === 'url' || $action_type === 'random' ) { | |
| 445 | + if ( in_array( $code, array( 301, 302, 307, 308 ), true ) ) { | |
| 446 | + return $code; | |
| 447 | + } | |
| 448 | + } | |
| 449 | + | |
| 450 | + if ( $action_type === 'error' ) { | |
| 451 | + if ( in_array( $code, array( 401, 404, 410 ), true ) ) { | |
| 452 | + return $code; | |
| 453 | + } | |
| 454 | + } | |
| 455 | + | |
| 456 | + return 0; | |
| 457 | + } | |
| 458 | + | |
| 459 | + protected function get_group( $group_id ) { | |
| 460 | + $group_id = intval( $group_id, 10 ); | |
| 461 | + | |
| 462 | + if ( ! Red_Group::get( $group_id ) ) { | |
| 463 | + return new WP_Error( 'redirect', __( 'Invalid group when creating redirect', 'redirection' ) ); | |
| 464 | + } | |
| 465 | + | |
| 466 | + return $group_id; | |
| 467 | + } | |
| 468 | + | |
| 469 | + protected function get_url( $url, $regex ) { | |
| 470 | + $url = self::sanitize_url( $url, $regex ); | |
| 471 | + | |
| 472 | + if ( $url === '' ) { | |
| 473 | + return new WP_Error( 'redirect', __( 'Invalid source URL', 'redirection' ) ); | |
| 474 | + } | |
| 475 | + | |
| 476 | + return $url; | |
| 477 | + } | |
| 478 | + | |
| 479 | + protected function auto_generate() { | |
| 480 | + $options = red_get_options(); | |
| 481 | + $url = ''; | |
| 482 | + | |
| 483 | + if ( isset( $options['auto_target'] ) && $options['auto_target'] ) { | |
| 484 | + $id = time(); | |
| 485 | + $url = str_replace( '$dec$', $id, $options['auto_target'] ); | |
| 486 | + $url = str_replace( '$hex$', sprintf( '%x', $id ), $url ); | |
| 487 | + } | |
| 488 | + | |
| 489 | + return $url; | |
| 490 | + } | |
| 491 | + | |
| 492 | + public function sanitize_url( $url, $regex = false ) { | |
| 493 | + // Make sure that the old URL is relative | |
| 494 | + $url = preg_replace( '@^https?://(.*?)/@', '/', $url ); | |
| 495 | + $url = preg_replace( '@^https?://(.*?)$@', '/', $url ); | |
| 496 | + | |
| 497 | + // No hash | |
| 498 | + $url = preg_replace( '/#.*$/', '', $url ); | |
| 499 | + | |
| 500 | + // No new lines | |
| 501 | + $url = preg_replace( "/[\r\n\t].*?$/s", '', $url ); | |
| 502 | + | |
| 503 | + // Clean control codes | |
| 504 | + $url = preg_replace( '/[^\PC\s]/u', '', $url ); | |
| 505 | + | |
| 506 | + // Ensure a slash at start | |
| 507 | + if ( substr( $url, 0, 1 ) !== '/' && $regex === false ) { | |
| 508 | + $url = '/'.$url; | |
| 509 | + } | |
| 510 | + | |
| 511 | + return $url; | |
| 530 | 512 | } |
| 531 | 513 | } |