PluginProbe
Redirection / 4.1
Redirection v4.1
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 4.1, at models/fixer.php

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