PluginProbe
Redirection / 3.7
Redirection v3.7
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.7, at models/fixer.php

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