Completed
Push — memberships/widget ( e31ee1...dba714 )
by
unknown
88:44 queued 79:07
created

Jetpack_Client_Server::do_exit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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() );
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...
27
28
			$tracking->record_user_event( 'jpc_client_authorize_fail', array(
29
				'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...
30
				'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...
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'] ) : '';
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...
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 );
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...
86
		}
87
88
		$cap = Jetpack::translate_role_to_cap( $role );
89
		if ( ! $cap ) {
90
			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...
91
		}
92
93
		if ( ! empty( $data['error'] ) ) {
94
			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...
95
		}
96
97
		if ( ! isset( $data['state'] ) ) {
98
			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...
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
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...
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
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...
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
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...
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
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...
118
			if ( empty( $code ) ) {
119
				$code = 'invalid_token';
120
			}
121
			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...
122
		}
123
124
		if ( ! $token ) {
125
			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...
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
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...
188
		}
189
190
		$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...
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
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...
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
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...
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
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...
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
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...
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
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...
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
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...
256
		}
257
258
		if ( empty( $json->scope ) ) {
259
			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...
260
		}
261
262
		@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...
263
		if ( empty( $role ) || empty( $hmac ) ) {
264
			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...
265
		}
266
267
		if ( Jetpack::sign_role( $role ) !== $json->scope ) {
268
			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...
269
		}
270
271
		if ( ! $cap = Jetpack::translate_role_to_cap( $role ) ) {
272
			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...
273
		}
274
275
		if ( ! current_user_can( $cap ) ) {
276
			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...
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