Completed
Push — add/mailchimp-groups-merge-fie... ( c88508...48f203 )
by
unknown
07:48 queued 01:05
created

Jetpack_Client_Server::client_authorize()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 8
nop 0
dl 0
loc 44
rs 9.216
c 0
b 0
f 0
1
<?php
2
3
use Automattic\Jetpack\Connection\Client;
4
use Automattic\Jetpack\Connection\Utils as Connection_Utils;
5
use Automattic\Jetpack\Roles;
6
use Automattic\Jetpack\Tracking;
7
8
/**
9
 * Client = Plugin
10
 * Client Server = API Methods the Plugin must respond to
11
 */
12
class Jetpack_Client_Server {
13
14
	/**
15
	 * Authorizations
16
	 */
17
	function client_authorize() {
18
		$data              = stripslashes_deep( $_GET );
19
		$data['auth_type'] = 'client';
20
		$roles             = new Roles();
21
		$role              = $roles->translate_current_user_to_role();
22
		$redirect          = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
23
24
		check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
25
26
		$tracking = new Tracking();
27
		$result   = $this->authorize( $data );
28
		if ( is_wp_error( $result ) ) {
29
			Jetpack::state( 'error', $result->get_error_code() );
0 ignored issues
show
Bug introduced by
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...
30
31
			$tracking->record_user_event(
32
				'jpc_client_authorize_fail',
33
				array(
34
					'error_code'    => $result->get_error_code(),
0 ignored issues
show
Bug introduced by
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...
35
					'error_message' => $result->get_error_message(),
0 ignored issues
show
Bug introduced by
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...
36
				)
37
			);
38
		} else {
39
			/**
40
			 * Fires after the Jetpack client is authorized to communicate with WordPress.com.
41
			 *
42
			 * @since 4.2.0
43
			 *
44
			 * @param int Jetpack Blog ID.
45
			 */
46
			do_action( 'jetpack_client_authorized', Jetpack_Options::get_option( 'id' ) );
47
		}
48
49
		if ( wp_validate_redirect( $redirect ) ) {
50
			// Exit happens below in $this->do_exit()
51
			wp_safe_redirect( $redirect );
52
		} else {
53
			// Exit happens below in $this->do_exit()
54
			wp_safe_redirect( Jetpack::admin_url() );
55
		}
56
57
		$tracking->record_user_event( 'jpc_client_authorize_success' );
58
59
		$this->do_exit();
60
	}
61
62
	function authorize( $data = array() ) {
63
		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
0 ignored issues
show
Unused Code introduced by
$redirect is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
64
65
		$jetpack_unique_connection = Jetpack_Options::get_option( 'unique_connection' );
66
		// Checking if site has been active/connected previously before recording unique connection
67
		if ( ! $jetpack_unique_connection ) {
68
			// jetpack_unique_connection option has never been set
69
			$jetpack_unique_connection = array(
70
				'connected'    => 0,
71
				'disconnected' => 0,
72
				'version'      => '3.6.1',
73
			);
74
75
			update_option( 'jetpack_unique_connection', $jetpack_unique_connection );
76
77
			// track unique connection
78
			$jetpack = $this->get_jetpack();
79
80
			$jetpack->stat( 'connections', 'unique-connection' );
81
			$jetpack->do_stats( 'server_side' );
82
		}
83
84
		// increment number of times connected
85
		$jetpack_unique_connection['connected'] += 1;
86
		Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection );
87
88
		$roles = new Roles();
89
		$role  = $roles->translate_current_user_to_role();
90
91
		if ( ! $role ) {
92
			return new Jetpack_Error( 'no_role', 'Invalid request.', 400 );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'no_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...
93
		}
94
95
		$cap = $roles->translate_role_to_cap( $role );
96
		if ( ! $cap ) {
97
			return new Jetpack_Error( 'no_cap', 'Invalid request.', 400 );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'no_cap'.

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...
98
		}
99
100
		if ( ! empty( $data['error'] ) ) {
101
			return new Jetpack_Error( $data['error'], 'Error included in the request.', 400 );
0 ignored issues
show
Unused Code introduced by
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...
102
		}
103
104
		if ( ! isset( $data['state'] ) ) {
105
			return new Jetpack_Error( 'no_state', 'Request must include state.', 400 );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'no_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...
106
		}
107
108
		if ( ! ctype_digit( $data['state'] ) ) {
109
			return new Jetpack_Error( $data['error'], 'State must be an integer.', 400 );
0 ignored issues
show
Unused Code introduced by
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...
110
		}
111
112
		$current_user_id = get_current_user_id();
113
		if ( $current_user_id != $data['state'] ) {
114
			return new Jetpack_Error( 'wrong_state', 'State does not match current user.', 400 );
0 ignored issues
show
Unused Code introduced by
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...
115
		}
116
117
		if ( empty( $data['code'] ) ) {
118
			return new Jetpack_Error( 'no_code', 'Request must include an authorization code.', 400 );
0 ignored issues
show
Unused Code introduced by
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...
119
		}
120
121
		$token = $this->get_token( $data );
122
123 View Code Duplication
		if ( is_wp_error( $token ) ) {
124
			$code = $token->get_error_code();
0 ignored issues
show
Bug introduced by
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...
125
			if ( empty( $code ) ) {
126
				$code = 'invalid_token';
127
			}
128
			return new Jetpack_Error( $code, $token->get_error_message(), 400 );
0 ignored issues
show
Bug introduced by
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...
Unused Code introduced by
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...
129
		}
130
131
		if ( ! $token ) {
132
			return new Jetpack_Error( 'no_token', 'Error generating token.', 400 );
0 ignored issues
show
Unused Code introduced by
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...
133
		}
134
135
		$is_master_user = ! Jetpack::is_active();
136
137
		Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
138
139
		if ( ! $is_master_user ) {
140
			Jetpack::state( 'message', 'linked' );
141
			// Don't activate anything since we are just connecting a user.
142
			return 'linked';
143
		}
144
145
		// If this site has been through the Jetpack Onboarding flow, delete the onboarding token
146
		Jetpack::invalidate_onboarding_token();
147
148
		// If redirect_uri is SSO, ensure SSO module is enabled
149
		parse_str( wp_parse_url( $data['redirect_uri'], PHP_URL_QUERY ), $redirect_options );
150
151
		/** This filter is documented in class.jetpack-cli.php */
152
		$jetpack_start_enable_sso = apply_filters( 'jetpack_start_enable_sso', true );
153
154
		$activate_sso = (
155
			isset( $redirect_options['action'] ) &&
156
			'jetpack-sso' === $redirect_options['action'] &&
157
			$jetpack_start_enable_sso
158
		);
159
160
		$do_redirect_on_error = ( 'client' === $data['auth_type'] );
161
162
		Jetpack::handle_post_authorization_actions( $activate_sso, $do_redirect_on_error );
163
164
		return 'authorized';
165
	}
166
167
	public static function deactivate_plugin( $probable_file, $probable_title ) {
168
		include_once ABSPATH . 'wp-admin/includes/plugin.php';
169
		if ( is_plugin_active( $probable_file ) ) {
170
			deactivate_plugins( $probable_file );
171
			return 1;
172
		} else {
173
			// If the plugin is not in the usual place, try looking through all active plugins.
174
			$active_plugins = Jetpack::get_active_plugins();
175
			foreach ( $active_plugins as $plugin ) {
176
				$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
177
				if ( $data['Name'] == $probable_title ) {
178
					deactivate_plugins( $plugin );
179
					return 1;
180
				}
181
			}
182
		}
183
184
		return 0;
185
	}
186
187
	/**
188
	 * @return object|WP_Error
189
	 */
190
	function get_token( $data ) {
191
		$roles = new Roles();
192
		$role  = $roles->translate_current_user_to_role();
193
194
		if ( ! $role ) {
195
			return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
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...
196
		}
197
198
		$client_secret = Jetpack_Data::get_access_token();
0 ignored issues
show
Deprecated Code introduced by
The method Jetpack_Data::get_access_token() has been deprecated with message: 7.5 Use Connection_Manager instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
199
		if ( ! $client_secret ) {
200
			return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
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...
201
		}
202
203
		$redirect     = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
204
		$redirect_uri = ( 'calypso' === $data['auth_type'] )
205
			? $data['redirect_uri']
206
			: add_query_arg(
207
				array(
208
					'action'   => 'authorize',
209
					'_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
210
					'redirect' => $redirect ? urlencode( $redirect ) : false,
211
				),
212
				menu_page_url( 'jetpack', false )
213
			);
214
215
		// inject identity for analytics
216
		$tracks          = new Automattic\Jetpack\Tracking();
217
		$tracks_identity = $tracks->tracks_get_identity( get_current_user_id() );
218
219
		$body = array(
220
			'client_id'     => Jetpack_Options::get_option( 'id' ),
221
			'client_secret' => $client_secret->secret,
222
			'grant_type'    => 'authorization_code',
223
			'code'          => $data['code'],
224
			'redirect_uri'  => $redirect_uri,
225
			'_ui'           => $tracks_identity['_ui'],
226
			'_ut'           => $tracks_identity['_ut'],
227
		);
228
229
		$args     = array(
230
			'method'  => 'POST',
231
			'body'    => $body,
232
			'headers' => array(
233
				'Accept' => 'application/json',
234
			),
235
		);
236
		$response = Client::_wp_remote_request( Connection_Utils::fix_url_for_bad_hosts( Jetpack::connection()->api_url( 'token' ) ), $args );
237
238
		if ( is_wp_error( $response ) ) {
239
			return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
0 ignored issues
show
Unused Code introduced by
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...
240
		}
241
242
		$code   = wp_remote_retrieve_response_code( $response );
243
		$entity = wp_remote_retrieve_body( $response );
244
245
		if ( $entity ) {
246
			$json = json_decode( $entity );
247
		} else {
248
			$json = false;
249
		}
250
251
		if ( 200 != $code || ! empty( $json->error ) ) {
252
			if ( empty( $json->error ) ) {
253
				return new Jetpack_Error( 'unknown', '', $code );
0 ignored issues
show
Unused Code introduced by
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...
254
			}
255
256
			$error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
257
258
			return new Jetpack_Error( (string) $json->error, $error_description, $code );
0 ignored issues
show
Unused Code introduced by
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...
259
		}
260
261
		if ( empty( $json->access_token ) || ! is_scalar( $json->access_token ) ) {
262
			return new Jetpack_Error( 'access_token', '', $code );
0 ignored issues
show
Unused Code introduced by
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...
263
		}
264
265
		if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
266
			return new Jetpack_Error( 'token_type', '', $code );
0 ignored issues
show
Unused Code introduced by
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...
267
		}
268
269
		if ( empty( $json->scope ) ) {
270
			return new Jetpack_Error( 'scope', 'No Scope', $code );
0 ignored issues
show
Unused Code introduced by
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...
271
		}
272
273
		@list( $role, $hmac ) = explode( ':', $json->scope );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
274
		if ( empty( $role ) || empty( $hmac ) ) {
275
			return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
0 ignored issues
show
Unused Code introduced by
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...
276
		}
277
278
		if ( Jetpack::connection()->sign_role( $role ) !== $json->scope ) {
279
			return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
0 ignored issues
show
Unused Code introduced by
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...
280
		}
281
282
		$cap = $roles->translate_role_to_cap( $role );
283
		if ( ! $cap ) {
284
			return new Jetpack_Error( 'scope', 'No Cap', $code );
0 ignored issues
show
Unused Code introduced by
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...
285
		}
286
287
		if ( ! current_user_can( $cap ) ) {
288
			return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
0 ignored issues
show
Unused Code introduced by
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...
289
		}
290
291
		/**
292
		 * Fires after user has successfully received an auth token.
293
		 *
294
		 * @since 3.9.0
295
		 */
296
		do_action( 'jetpack_user_authorized' );
297
298
		return (string) $json->access_token;
299
	}
300
301
	public function get_jetpack() {
302
		return Jetpack::init();
303
	}
304
305
	public function do_exit() {
306
		exit;
307
	}
308
}
309