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

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

291 lines 8.7 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 if ( is_wp_error( $response ) ) {
217 return $response;
218 }
219
220 $http_code = wp_remote_retrieve_response_code( $response );
221
222 $specific = 'REST API returns an error code';
223 if ( $http_code === 200 ) {
224 $json = $this->get_json( $response['body'] );
225
226 if ( $json || $response['body'] === '0' ) {
227 return true;
228 } else {
229 $specific = 'REST API returned invalid JSON data. This is probably an error page of some kind and indicates it has been disabled';
230 $specific .= ' - ' . json_last_error_msg();
231 }
232 } elseif ( $http_code === 301 || $http_code === 302 ) {
233 $specific = 'REST API is being redirected. This indicates it has been disabled or you have a trailing slash redirect.';
234 } elseif ( $http_code === 404 ) {
235 $specific = 'REST API is returning a 404 error. This indicates it has been disabled.';
236 } elseif ( $http_code ) {
237 $specific = 'REST API returned a ' . $http_code . ' code.';
238 }
239
240 return new WP_Error( 'redirection', $specific . ' (' . ( $http_code ? $http_code : 'unknown' ) . ' - ' . $url . ')' );
241 }
242
243 private function get_json( $body ) {
244 if ( strpos( bin2hex( $body ), 'efbbbf' ) !== false ) {
245 $body = substr( $body, 3 );
246 }
247
248 return @json_decode( $body, true );
249 }
250
251 private function fix_db() {
252 $database = new RE_Database();
253
254 try {
255 $database->create_tables();
256 } catch ( Exception $e ) {
257 return new WP_Error( __( 'Failed to fix database tables', 'redirection' ) );
258 }
259
260 return true;
261 }
262
263 private function fix_groups() {
264 if ( Red_Group::create( 'new group', 1 ) === false ) {
265 return new WP_Error( __( 'Unable to create group', 'redirection' ) );
266 }
267
268 return true;
269 }
270
271 private function fix_redirect_groups() {
272 global $wpdb;
273
274 $missing = $this->get_missing();
275
276 foreach ( $missing as $row ) {
277 $wpdb->update( $wpdb->prefix . 'redirection_items', array( 'group_id' => $this->get_valid_group() ), array( 'id' => $row->id ) );
278 }
279 }
280
281 private function fix_monitor() {
282 red_set_options( array( 'monitor_post' => $this->get_valid_group() ) );
283 }
284
285 private function get_valid_group() {
286 $groups = Red_Group::get_all();
287
288 return $groups[0]['id'];
289 }
290 }
291