PluginProbe
Redirection / 3.3
Redirection v3.3
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 / fixer.php

fixer.php in Redirection 3.3, at models/fixer.php

285 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 include_once dirname( REDIRECTION_FILE ) . '/models/database.php';
4
5 class Red_Fixer {
6 public function get_status() {
7 global $wpdb;
8
9 $options = red_get_options();
10
11 $database = new RE_Database();
12 $groups = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_groups" ), 10 );
13 $bad_group = $this->get_missing();
14 $monitor_group = $options['monitor_post'];
15 $valid_monitor = Red_Group::get( $monitor_group ) || $monitor_group === 0;
16 $rest_status = $this->get_rest_status();
17
18 $result = array(
19 $rest_status,
20 $this->get_rest_route_status( $rest_status ),
21 array_merge( array(
22 'id' => 'db',
23 'name' => __( 'Database tables', 'redirection' ),
24 ), $database->get_status() ),
25 array(
26 'name' => __( 'Valid groups', 'redirection' ),
27 'id' => 'groups',
28 'message' => $groups === 0 ? __( 'No valid groups, so you will not be able to create any redirects', 'redirection' ) : __( 'Valid groups detected', 'redirection' ),
29 'status' => $groups === 0 ? 'problem' : 'good',
30 ),
31 array(
32 'name' => __( 'Valid redirect group', 'redirection' ),
33 'id' => 'redirect_groups',
34 'message' => count( $bad_group ) > 0 ? __( 'Redirects with invalid groups detected', 'redirection' ) : __( 'All redirects have a valid group', 'redirection' ),
35 'status' => count( $bad_group ) > 0 ? 'problem' : 'good',
36 ),
37 array(
38 'name' => __( 'Post monitor group', 'redirection' ),
39 'id' => 'monitor',
40 'message' => $valid_monitor === false ? __( 'Post monitor group is invalid', 'redirection' ) : __( 'Post monitor group is valid' ),
41 'status' => $valid_monitor === false ? 'problem' : 'good',
42 ),
43 $this->get_http_settings(),
44 );
45
46 return $result;
47 }
48
49 private function get_http_settings() {
50 $site = parse_url( get_site_url(), PHP_URL_SCHEME );
51 $home = parse_url( get_home_url(), PHP_URL_SCHEME );
52
53 $message = __( 'Site and home are consistent', 'redirection' );
54 if ( $site !== $home ) {
55 $message = __( 'Site and home URL are inconsistent - please correct from your General settings', 'redirection' );
56 $message .= ' - ' . get_site_url() . ' !== ' . get_home_url();
57 }
58
59 return array(
60 'name' => __( 'Site and home protocol', 'redirection' ),
61 'id' => 'redirect_url',
62 'message' => $message,
63 'status' => $site === $home ? 'good' : 'problem',
64 );
65 }
66
67 private function get_rest_route_status( $status ) {
68 $result = array(
69 'name' => __( 'Redirection routes', 'redirection' ),
70 'id' => 'routes',
71 'status' => 'problem',
72 );
73
74 if ( $status['status'] === 'good' ) {
75 $response = $this->request_from_api( red_get_rest_api() );
76
77 $result['message'] = __( 'Redirection does not appear in your REST API routes. Have you disabled it with a plugin?', 'redirection' );
78
79 if ( $response && is_array( $response ) && isset( $response['body'] ) ) {
80 $json = $this->get_json( $response['body'] );
81
82 if ( isset( $json['success'] ) ) {
83 $result['message'] = __( 'Redirection routes are working', 'redirection' );
84 $result['status'] = 'good';
85 }
86 }
87 } else {
88 $result['message'] = __( 'REST API is not working so routes not checked', 'redirection' );
89 }
90
91 return $result;
92 }
93
94 public function get_rest_status() {
95 $status = array(
96 'name' => __( 'WordPress REST API', 'redirection' ),
97 'id' => 'rest',
98 'status' => 'good',
99 /* translators: %s: URL of REST API */
100 'message' => sprintf( __( 'WordPress REST API is working at %s', 'redirection' ), red_get_rest_api() ),
101 );
102
103 // Special case for OVH servers - this is as close as I can get to detecting mod_security
104 $options = red_get_options();
105 if ( $options['rest_api'] === 0 && strpos( php_uname( 'a' ), 'ovh' ) !== false ) {
106 red_set_options( array( 'rest_api' => 2 ) );
107 }
108
109 $result = $this->check_api( red_get_rest_api() );
110
111 if ( is_wp_error( $result ) ) {
112 $status['status'] = 'problem';
113 $status['message'] = $result->get_error_message();
114 }
115
116 return $status;
117 }
118
119 public function fix( $status ) {
120 foreach ( $status as $item ) {
121 if ( $item['status'] !== 'good' ) {
122 $fixer = 'fix_' . $item['id'];
123
124 if ( method_exists( $this, $fixer ) ) {
125 $result = $this->$fixer();
126 }
127
128 if ( is_wp_error( $result ) ) {
129 return $result;
130 }
131 }
132 }
133
134 return $this->get_status();
135 }
136
137 private function get_missing() {
138 global $wpdb;
139
140 return $wpdb->get_results( "SELECT {$wpdb->prefix}redirection_items.id FROM {$wpdb->prefix}redirection_items LEFT JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_items.group_id = {$wpdb->prefix}redirection_groups.id WHERE {$wpdb->prefix}redirection_groups.id IS NULL" );
141 }
142
143 public function fix_rest() {
144 // First check the default REST API
145 $result = $this->check_api( get_rest_url() );
146
147 if ( is_wp_error( $result ) ) {
148 $options = red_get_options();
149 if ( $options['https'] ) {
150 // Disable this just be to safe
151 red_set_options( array( 'https' => false ) );
152 }
153
154 // Try directly at index.php?rest_route
155 $rest_api = red_get_rest_api( REDIRECTION_API_JSON_INDEX );
156 $result = $this->check_api( $rest_api );
157
158 if ( is_wp_error( $result ) ) {
159 $rest_api = red_get_rest_api( REDIRECTION_API_ADMIN );
160 $response = $this->request_from_api( $rest_api );
161
162 if ( is_array( $response ) && isset( $response['body'] ) && $response['body'] === '0' ) {
163 red_set_options( array( 'rest_api' => 2 ) );
164 return true;
165 }
166
167 red_set_options( array( 'rest_api' => 0 ) );
168 return false;
169 }
170
171 // It worked! Save the URL
172 red_set_options( array( 'rest_api' => 1 ) );
173 return true;
174 }
175
176 // Working
177 red_set_options( array( 'rest_api' => 0 ) );
178 return true;
179 }
180
181 private function normalize_url( $url ) {
182 if ( substr( $url, 0, 4 ) !== 'http' ) {
183 $parts = parse_url( get_site_url() );
184 $url = ( isset( $parts['scheme'] ) ? $parts['scheme'] : 'http' ) . '://' . $parts['host'] . $url;
185 }
186
187 return $url;
188 }
189
190 private function request_from_api( $url ) {
191 $url = $this->normalize_url( $url . 'redirection/v1/plugin/test' );
192 $url = add_query_arg( '_wpnonce', wp_create_nonce( 'wp_rest' ), $url );
193 $options = array(
194 'cookies' => $_COOKIE,
195 'redirection' => 0,
196 'body' => '{}',
197 );
198
199 // For REST API calls set the content-type - some servers get tripped up on this
200 if ( strpos( $url, '/wp-json/' ) !== false || strpos( $url, 'rest_route' ) !== false ) {
201 $options['headers'] = array(
202 'content-type: application/json; charset=utf-8',
203 );
204 }
205
206 // Match our user agent
207 if ( Redirection_Request::get_user_agent() ) {
208 $options['user-agent'] = Redirection_Request::get_user_agent();
209 }
210
211 return wp_remote_post( $url, $options );
212 }
213
214 private function check_api( $url ) {
215 $response = $this->request_from_api( $url );
216 $http_code = wp_remote_retrieve_response_code( $response );
217
218 $specific = 'REST API returns an error code';
219 if ( $http_code === 200 ) {
220 $json = $this->get_json( $response['body'] );
221
222 if ( $json || $response['body'] === '0' ) {
223 return true;
224 } else {
225 $specific = 'REST API returned invalid JSON data. This is probably an error page of some kind and indicates it has been disabled';
226 $specific .= ' - ' . json_last_error_msg();
227 }
228 } elseif ( $http_code === 301 || $http_code === 302 ) {
229 $specific = 'REST API is being redirected. This indicates it has been disabled or you have a trailing slash redirect.';
230 } elseif ( $http_code === 404 ) {
231 $specific = 'REST API is returning 404 error. This indicates it has been disabled.';
232 }
233
234 return new WP_Error( 'redirection', $specific . ' (' . ( $http_code ? $http_code : '40x' ) . ' - ' . $url . ')' );
235 }
236
237 private function get_json( $body ) {
238 if ( strpos( bin2hex( $body ), 'efbbbf' ) !== false ) {
239 $body = substr( $body, 3 );
240 }
241
242 return @json_decode( $body, true );
243 }
244
245 private function fix_db() {
246 $database = new RE_Database();
247
248 try {
249 $database->create_tables();
250 } catch ( Exception $e ) {
251 return new WP_Error( __( 'Failed to fix database tables', 'redirection' ) );
252 }
253
254 return true;
255 }
256
257 private function fix_groups() {
258 if ( Red_Group::create( 'new group', 1 ) === false ) {
259 return new WP_Error( __( 'Unable to create group', 'redirection' ) );
260 }
261
262 return true;
263 }
264
265 private function fix_redirect_groups() {
266 global $wpdb;
267
268 $missing = $this->get_missing();
269
270 foreach ( $missing as $row ) {
271 $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'group_id' => $this->get_valid_group() ), array( 'id' => $row->id ) );
272 }
273 }
274
275 private function fix_monitor() {
276 red_set_options( array( 'monitor_post' => $this->get_valid_group() ) );
277 }
278
279 private function get_valid_group() {
280 $groups = Red_Group::get_all();
281
282 return $groups[0]['id'];
283 }
284 }
285