Completed
Push — memberships/widget ( e36f77...e31ee1 )
by
unknown
48:35 queued 32:12
created

class.jetpack-client-server.php (19 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use Automattic\Jetpack\Connection\Client;
4
use Automattic\Jetpack\Tracking;
5
6
/**
7
 * Client = Plugin
8
 * Client Server = API Methods the Plugin must respond to
9
 */
10
class Jetpack_Client_Server {
11
12
	/**
13
	 * Authorizations
14
	 */
15
	function client_authorize() {
16
		$data              = stripslashes_deep( $_GET );
17
		$data['auth_type'] = 'client';
18
		$role              = Jetpack::translate_current_user_to_role();
19
		$redirect          = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
20
21
		check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
22
23
		$tracking = new Tracking();
24
		$result = $this->authorize( $data );
25
		if ( is_wp_error( $result ) ) {
26
			Jetpack::state( 'error', $result->get_error_code() );
27
28
			$tracking->record_user_event( 'jpc_client_authorize_fail', array(
29
				'error_code' => $result->get_error_code(),
30
				'error_message' => $result->get_error_message()
31
			) );
32
		} else {
33
			/**
34
			 * Fires after the Jetpack client is authorized to communicate with WordPress.com.
35
			 *
36
			 * @since 4.2.0
37
			 *
38
			 * @param int Jetpack Blog ID.
39
			 */
40
			do_action( 'jetpack_client_authorized', Jetpack_Options::get_option( 'id' ) );
41
		}
42
43
		if ( wp_validate_redirect( $redirect ) ) {
44
			// Exit happens below in $this->do_exit()
45
			wp_safe_redirect( $redirect );
46
		} else {
47
			// Exit happens below in $this->do_exit()
48
			wp_safe_redirect( Jetpack::admin_url() );
49
		}
50
51
		$tracking->record_user_event( 'jpc_client_authorize_success' );
52
53
		$this->do_exit();
54
	}
55
56
	function authorize( $data = array() ) {
57
		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
58
59
		$jetpack_unique_connection = Jetpack_Options::get_option( 'unique_connection' );
60
		// Checking if site has been active/connected previously before recording unique connection
61
		if ( ! $jetpack_unique_connection ) {
62
			// jetpack_unique_connection option has never been set
63
			$jetpack_unique_connection = array(
64
				'connected'     => 0,
65
				'disconnected'  => 0,
66
				'version'       => '3.6.1',
67
			);
68
69
			update_option( 'jetpack_unique_connection', $jetpack_unique_connection );
70
71
			//track unique connection
72
			$jetpack = $this->get_jetpack();
73
74
			$jetpack->stat( 'connections', 'unique-connection' );
75
			$jetpack->do_stats( 'server_side' );
76
		}
77
78
		// increment number of times connected
79
		$jetpack_unique_connection['connected'] += 1;
80
		Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection );
81
82
		$role = Jetpack::translate_current_user_to_role();
83
84
		if ( ! $role ) {
85
			return new Jetpack_Error( 'no_role', 'Invalid request.', 400 );
86
		}
87
88
		$cap = Jetpack::translate_role_to_cap( $role );
89
		if ( ! $cap ) {
90
			return new Jetpack_Error( 'no_cap', 'Invalid request.', 400 );
91
		}
92
93
		if ( ! empty( $data['error'] ) ) {
94
			return new Jetpack_Error( $data['error'], 'Error included in the request.', 400 );
95
		}
96
97
		if ( ! isset( $data['state'] ) ) {
98
			return new Jetpack_Error( 'no_state', 'Request must include state.', 400 );
99
		}
100
101
		if ( ! ctype_digit( $data['state'] ) ) {
102
			return new Jetpack_Error( $data['error'], 'State must be an integer.', 400 );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with $data['error'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
103
		}
104
105
		$current_user_id = get_current_user_id();
106
		if ( $current_user_id != $data['state'] ) {
107
			return new Jetpack_Error( 'wrong_state', 'State does not match current user.', 400 );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'wrong_state'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
108
		}
109
110
		if ( empty( $data['code'] ) ) {
111
			return new Jetpack_Error( 'no_code', 'Request must include an authorization code.', 400 );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'no_code'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
112
		}
113
114
		$token = $this->get_token( $data );
115
116 View Code Duplication
		if ( is_wp_error( $token ) ) {
117
			$code = $token->get_error_code();
0 ignored issues
show
The method get_error_code() does not seem to exist on object<Jetpack_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
118
			if ( empty( $code ) ) {
119
				$code = 'invalid_token';
120
			}
121
			return new Jetpack_Error( $code, $token->get_error_message(), 400 );
0 ignored issues
show
The method get_error_message() does not seem to exist on object<Jetpack_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The call to Jetpack_Error::__construct() has too many arguments starting with $code.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
122
		}
123
124
		if ( ! $token ) {
125
			return new Jetpack_Error( 'no_token', 'Error generating token.', 400 );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'no_token'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
126
		}
127
128
		$is_master_user = ! Jetpack::is_active();
129
130
		Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
131
132
		if ( ! $is_master_user ) {
133
			Jetpack::state( 'message', 'linked' );
134
			// Don't activate anything since we are just connecting a user.
135
			return 'linked';
136
		}
137
138
		// If this site has been through the Jetpack Onboarding flow, delete the onboarding token
139
		Jetpack::invalidate_onboarding_token();
140
141
		// If redirect_uri is SSO, ensure SSO module is enabled
142
		parse_str( parse_url( $data['redirect_uri'], PHP_URL_QUERY ), $redirect_options );
143
144
		/** This filter is documented in class.jetpack-cli.php */
145
		$jetpack_start_enable_sso = apply_filters( 'jetpack_start_enable_sso', true );
146
147
		$activate_sso = (
148
			isset( $redirect_options['action'] ) &&
149
			'jetpack-sso' === $redirect_options['action'] &&
150
			$jetpack_start_enable_sso
151
		);
152
153
		$do_redirect_on_error = ( 'client' === $data['auth_type'] );
154
155
		Jetpack::handle_post_authorization_actions( $activate_sso, $do_redirect_on_error );
156
157
		return 'authorized';
158
	}
159
160
	public static function deactivate_plugin( $probable_file, $probable_title ) {
161
		include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
162
		if ( is_plugin_active( $probable_file ) ) {
163
			deactivate_plugins( $probable_file );
164
			return 1;
165
		} else {
166
			// If the plugin is not in the usual place, try looking through all active plugins.
167
			$active_plugins = Jetpack::get_active_plugins();
168
			foreach ( $active_plugins as $plugin ) {
169
				$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
170
				if ( $data['Name'] == $probable_title ) {
171
					deactivate_plugins( $plugin );
172
					return 1;
173
				}
174
			}
175
		}
176
177
		return 0;
178
	}
179
180
	/**
181
	 * @return object|WP_Error
182
	 */
183
	function get_token( $data ) {
184
		$role = Jetpack::translate_current_user_to_role();
185
186
		if ( ! $role ) {
187
			return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'role'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
188
		}
189
190
		$client_secret = Jetpack_Data::get_access_token();
191
		if ( ! $client_secret ) {
192
			return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'client_secret'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
193
		}
194
195
		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
196
		$redirect_uri = ( 'calypso' === $data['auth_type'] )
197
			? $data['redirect_uri']
198
			: add_query_arg( array(
199
				'action' => 'authorize',
200
				'_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
201
				'redirect' => $redirect ? urlencode( $redirect ) : false,
202
			), menu_page_url( 'jetpack', false ) );
203
204
		// inject identity for analytics
205
		$tracks = new Automattic\Jetpack\Tracking();
206
		$tracks_identity = $tracks->tracks_get_identity( get_current_user_id() );
207
208
		$body = array(
209
			'client_id' => Jetpack_Options::get_option( 'id' ),
210
			'client_secret' => $client_secret->secret,
211
			'grant_type' => 'authorization_code',
212
			'code' => $data['code'],
213
			'redirect_uri' => $redirect_uri,
214
			'_ui' => $tracks_identity['_ui'],
215
			'_ut' => $tracks_identity['_ut'],
216
		);
217
218
		$args = array(
219
			'method' => 'POST',
220
			'body' => $body,
221
			'headers' => array(
222
				'Accept' => 'application/json',
223
			),
224
		);
225
		$response = Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ) ), $args );
226
227
		if ( is_wp_error( $response ) ) {
228
			return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'token_http_request_failed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
229
		}
230
231
		$code = wp_remote_retrieve_response_code( $response );
232
		$entity = wp_remote_retrieve_body( $response );
233
234
		if ( $entity ) {
235
			$json = json_decode( $entity );
236
		} else {
237
			$json = false;
238
		}
239
240
		if ( 200 != $code || ! empty( $json->error ) ) {
241
			if ( empty( $json->error ) ) {
242
				return new Jetpack_Error( 'unknown', '', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'unknown'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
243
			}
244
245
			$error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
246
247
			return new Jetpack_Error( (string) $json->error, $error_description, $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with (string) $json->error.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
248
		}
249
250
		if ( empty( $json->access_token ) || ! is_scalar( $json->access_token ) ) {
251
			return new Jetpack_Error( 'access_token', '', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'access_token'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
252
		}
253
254
		if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
255
			return new Jetpack_Error( 'token_type', '', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'token_type'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
256
		}
257
258
		if ( empty( $json->scope ) ) {
259
			return new Jetpack_Error( 'scope', 'No Scope', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'scope'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
260
		}
261
262
		@list( $role, $hmac ) = explode( ':', $json->scope );
263
		if ( empty( $role ) || empty( $hmac ) ) {
264
			return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'scope'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
265
		}
266
267
		if ( Jetpack::sign_role( $role ) !== $json->scope ) {
268
			return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'scope'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
269
		}
270
271
		if ( ! $cap = Jetpack::translate_role_to_cap( $role ) ) {
272
			return new Jetpack_Error( 'scope', 'No Cap', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'scope'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
273
		}
274
275
		if ( ! current_user_can( $cap ) ) {
276
			return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
0 ignored issues
show
The call to Jetpack_Error::__construct() has too many arguments starting with 'scope'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
277
		}
278
279
		/**
280
		 * Fires after user has successfully received an auth token.
281
		 *
282
		 * @since 3.9.0
283
		 */
284
		do_action( 'jetpack_user_authorized' );
285
286
		return (string) $json->access_token;
287
	}
288
289
	public function get_jetpack() {
290
		return Jetpack::init();
291
	}
292
293
	public function do_exit() {
294
		exit;
295
	}
296
}
297