Completed
Push — move-action-for-authorization-... ( 6cb92a )
by
unknown
20:34 queued 09:27
created

class.jetpack-client-server.php (1 issue)

Labels
Severity

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
/**
4
 * Client = Plugin
5
 * Client Server = API Methods the Plugin must respond to
6
 */
7
class Jetpack_Client_Server {
8
9
	/**
10
	 * Authorizations
11
	 */
12
	function client_authorize() {
13
		$data              = stripslashes_deep( $_GET );
14
		$data['auth_type'] = 'client';
15
		$role              = Jetpack::translate_current_user_to_role();
16
		$redirect          = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
17
18
		check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
19
20
		$result = $this->authorize( $data );
21
		if ( is_wp_error( $result ) ) {
22
			Jetpack::state( 'error', $result->get_error_code() );
23
		}
24
25
		if ( wp_validate_redirect( $redirect ) ) {
26
			wp_safe_redirect( $redirect );
27
		} else {
28
			wp_safe_redirect( Jetpack::admin_url() );
29
		}
30
31
		/**
32
		 * Fires after the Jetpack client is authorized to communicate with WordPress.com.
33
		 *
34
		 * @since 4.2.0
35
		 *
36
		 * @param int Jetpack Blog ID.
37
		 */
38
		do_action( 'jetpack_client_authorized', Jetpack_Options::get_option( 'id' ) );
39
40
		$this->do_exit();
41
	}
42
43
	function authorize( $data = array() ) {
44
		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
45
46
		$jetpack_unique_connection = Jetpack_Options::get_option( 'unique_connection' );
47
		// Checking if site has been active/connected previously before recording unique connection
48
		if ( ! $jetpack_unique_connection ) {
49
			// jetpack_unique_connection option has never been set
50
			$jetpack_unique_connection = array(
51
				'connected'     => 0,
52
				'disconnected'  => 0,
53
				'version'       => '3.6.1',
54
			);
55
56
			update_option( 'jetpack_unique_connection', $jetpack_unique_connection );
57
58
			//track unique connection
59
			$jetpack = $this->get_jetpack();;
60
61
			$jetpack->stat( 'connections', 'unique-connection' );
62
			$jetpack->do_stats( 'server_side' );
63
		}
64
65
		// increment number of times connected
66
		$jetpack_unique_connection['connected'] += 1;
67
		Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection );
68
69
		$role = Jetpack::translate_current_user_to_role();
70
71
		if ( ! $role ) {
72
			return new Jetpack_Error( 'no_role', 'Invalid request.', 400 );
73
		}
74
75
		$cap = Jetpack::translate_role_to_cap( $role );
76
		if ( ! $cap ) {
77
			return new Jetpack_Error( 'no_cap', 'Invalid request.', 400 );
78
		}
79
80
		if ( ! empty( $data['error'] ) ) {
81
			return new Jetpack_Error( $data['error'], 'Error included in the request.', 400 );
82
		}
83
84
		if ( ! isset( $data['state'] ) ) {
85
			return new Jetpack_Error( 'no_state', 'Request must include state.', 400 );
86
		}
87
88
		if ( ! ctype_digit( $data['state'] ) ) {
89
			return new Jetpack_Error( $data['error'], 'State must be an integer.', 400 );
90
		}
91
92
		$current_user_id = get_current_user_id();
93
		if ( $current_user_id != $data['state'] ) {
94
			return new Jetpack_Error( 'wrong_state', 'State does not match current user.', 400 );
95
		}
96
97
		if ( empty( $data['code'] ) ) {
98
			return new Jetpack_Error( 'no_code', 'Request must include an authorization code.', 400 );
99
		}
100
101
		$token = $this->get_token( $data );
102
103
		if ( is_wp_error( $token ) ) {
104
			$code = $token->get_error_code();
105
			if ( empty( $code ) ) {
106
				$code = 'invalid_token';
107
			}
108
			return new Jetpack_Error( $code, $token->get_error_message(), 400 );
109
		}
110
111
		if ( ! $token ) {
112
			return new Jetpack_Error( 'no_token', 'Error generating token.', 400 );
113
		}
114
115
		$is_master_user = ! Jetpack::is_active();
116
117
		$token_set = Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
0 ignored issues
show
Are you sure the assignment to $token_set is correct as \Jetpack::update_user_to...r_id), $is_master_user) (which targets Jetpack::update_user_token()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
118
119
		if ( ! $token_set ) {
120
			return new Jetpack_Error( 'token_not_saved', 'Error saving token.', 400 );
121
		}
122
123
		/**
124
		 * Fires after user has successfully received an auth token.
125
		 *
126
		 * @since 3.9.0
127
		 */
128
		do_action( 'jetpack_user_authorized' );
129
130
131
		if ( ! $is_master_user ) {
132
			Jetpack::state( 'message', 'linked' );
133
			// Don't activate anything since we are just connecting a user.
134
			return 'linked';
135
		}
136
137
		$redirect_on_activation_error = ( 'client' === $data['auth_type'] ) ? true : false;
138
		if ( $active_modules = Jetpack_Options::get_option( 'active_modules' ) ) {
139
			Jetpack::delete_active_modules();
140
141
			Jetpack::activate_default_modules( 999, 1, $active_modules, $redirect_on_activation_error );
142
		} else {
143
			Jetpack::activate_default_modules( false, false, array(), $redirect_on_activation_error );
144
		}
145
146
		// If redirect_uri is SSO, ensure SSO module is enabled
147
		parse_str( parse_url( $data['redirect_uri'], PHP_URL_QUERY ), $redirect_options );
148
		if ( isset( $redirect_options['action'] ) && 'jetpack-sso' === $redirect_options['action'] ) {
149
			Jetpack::activate_module( 'sso', false, false );
150
		}
151
152
		// Since this is a fresh connection, be sure to clear out IDC options
153
		Jetpack_IDC::clear_all_idc_options();
154
155
		// Start nonce cleaner
156
		wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
157
		wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
158
159
		Jetpack::state( 'message', 'authorized' );
160
		return 'authorized';
161
	}
162
163
	public static function deactivate_plugin( $probable_file, $probable_title ) {
164
		include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
165
		if ( is_plugin_active( $probable_file ) ) {
166
			deactivate_plugins( $probable_file );
167
			return 1;
168
		} else {
169
			// If the plugin is not in the usual place, try looking through all active plugins.
170
			$active_plugins = Jetpack::get_active_plugins();
171
			foreach ( $active_plugins as $plugin ) {
172
				$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
173
				if ( $data['Name'] == $probable_title ) {
174
					deactivate_plugins( $plugin );
175
					return 1;
176
				}
177
			}
178
		}
179
180
		return 0;
181
	}
182
183
	/**
184
	 * @return object|WP_Error
185
	 */
186
	function get_token( $data ) {
187
		$role = Jetpack::translate_current_user_to_role();
188
189
		if ( ! $role ) {
190
			return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
191
		}
192
193
		$client_secret = Jetpack_Data::get_access_token();
194
		if ( ! $client_secret ) {
195
			return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
196
		}
197
198
		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
199
		$redirect_uri = ( 'calypso' === $data['auth_type'] )
200
			? $data['redirect_uri']
201
			: add_query_arg( array(
202
				'action' => 'authorize',
203
				'_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
204
				'redirect' => $redirect ? urlencode( $redirect ) : false,
205
			), menu_page_url( 'jetpack', false ) );
206
207
		$body = array(
208
			'client_id' => Jetpack_Options::get_option( 'id' ),
209
			'client_secret' => $client_secret->secret,
210
			'grant_type' => 'authorization_code',
211
			'code' => $data['code'],
212
			'redirect_uri' => $redirect_uri,
213
		);
214
215
		$args = array(
216
			'method' => 'POST',
217
			'body' => $body,
218
			'headers' => array(
219
				'Accept' => 'application/json',
220
			),
221
		);
222
		$response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ) ), $args );
223
224
		if ( is_wp_error( $response ) ) {
225
			return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
226
		}
227
228
		$code = wp_remote_retrieve_response_code( $response );
229
		$entity = wp_remote_retrieve_body( $response );
230
231
		if ( $entity ) {
232
			$json = json_decode( $entity );
233
		} else {
234
			$json = false;
235
		}
236
237
		if ( 200 != $code || ! empty( $json->error ) ) {
238
			if ( empty( $json->error ) ) {
239
				return new Jetpack_Error( 'unknown', '', $code );
240
			}
241
242
			$error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
243
244
			return new Jetpack_Error( (string) $json->error, $error_description, $code );
245
		}
246
247
		if ( empty( $json->access_token ) || ! is_scalar( $json->access_token ) ) {
248
			return new Jetpack_Error( 'access_token', '', $code );
249
		}
250
251
		if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
252
			return new Jetpack_Error( 'token_type', '', $code );
253
		}
254
255
		if ( empty( $json->scope ) ) {
256
			return new Jetpack_Error( 'scope', 'No Scope', $code );
257
		}
258
259
		@list( $role, $hmac ) = explode( ':', $json->scope );
260
		if ( empty( $role ) || empty( $hmac ) ) {
261
			return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
262
		}
263
264
		if ( Jetpack::sign_role( $role ) !== $json->scope ) {
265
			return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
266
		}
267
268
		if ( ! $cap = Jetpack::translate_role_to_cap( $role ) ) {
269
			return new Jetpack_Error( 'scope', 'No Cap', $code );
270
		}
271
272
		if ( ! current_user_can( $cap ) ) {
273
			return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
274
		}
275
276
		return (string) $json->access_token;
277
	}
278
279
	public function get_jetpack() {
280
		return Jetpack::init();
281
	}
282
283
	public function do_exit() {
284
		exit;
285
	}
286
}
287