diff options
Diffstat (limited to 'plugins/jetpack/class.jetpack.php')
-rw-r--r-- | plugins/jetpack/class.jetpack.php | 275 |
1 files changed, 166 insertions, 109 deletions
diff --git a/plugins/jetpack/class.jetpack.php b/plugins/jetpack/class.jetpack.php index da45ae85..c3473223 100644 --- a/plugins/jetpack/class.jetpack.php +++ b/plugins/jetpack/class.jetpack.php @@ -22,6 +22,8 @@ jetpack_do_activate (bool) Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs) */ +require_once( JETPACK__PLUGIN_DIR . '_inc/lib/class.media.php' ); + class Jetpack { public $xmlrpc_server = null; @@ -428,7 +430,6 @@ class Jetpack { */ add_action( 'init', array( $this, 'deprecated_hooks' ) ); - /* * Load things that should only be in Network Admin. * @@ -474,7 +475,13 @@ class Jetpack { // Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on. add_filter( 'pre_option_enable_xmlrpc', '__return_true' ); - } elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) { + } elseif ( + is_admin() && + isset( $_POST['action'] ) && ( + 'jetpack_upload_file' == $_POST['action'] || + 'jetpack_update_file' == $_POST['action'] + ) + ) { $this->require_jetpack_authentication(); $this->add_remote_request_handlers(); } else { @@ -865,7 +872,7 @@ class Jetpack { */ function devicepx() { if ( Jetpack::is_active() ) { - wp_enqueue_script( 'devicepx', set_url_scheme( 'http://s0.wp.com/wp-content/js/devicepx-jetpack.js' ), array(), gmdate( 'oW' ), true ); + wp_enqueue_script( 'devicepx', 'https://s0.wp.com/wp-content/js/devicepx-jetpack.js', array(), gmdate( 'oW' ), true ); } } @@ -1113,6 +1120,26 @@ class Jetpack { } /** + * Wrapper for core's get_avatar_url(). This one is deprecated. + * + * @deprecated 4.7 use get_avatar_url instead. + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param bool $force_display Whether to force it to return an avatar even if show_avatars is disabled + * + * @return array + */ + public static function get_avatar_url( $id_or_email, $size = 96, $default = '', $force_display = false ) { + _deprecated_function( __METHOD__, 'jetpack-4.7', 'get_avatar_url' ); + return get_avatar_url( $id_or_email, array( + 'size' => $size, + 'default' => $default, + 'force_default' => $force_display, + ) ); + } + + /** * jetpack_updates is saved in the following schema: * * array ( @@ -1217,14 +1244,15 @@ class Jetpack { // Set the default options if ( ! $plan ) { - $plan = array( - 'product_slug' => 'jetpack_free', - 'supports' => array(), + $plan = array( + 'product_slug' => 'jetpack_free', + 'supports' => array(), + 'class' => 'free', ); } // Define what paid modules are supported by personal plans - $personal_plans = array( + $personal_plans = array( 'jetpack_personal', 'jetpack_personal_monthly', ); @@ -1233,6 +1261,7 @@ class Jetpack { $plan['supports'] = array( 'akismet', ); + $plan['class'] = 'personal'; } // Define what paid modules are supported by premium plans @@ -1246,7 +1275,9 @@ class Jetpack { 'videopress', 'akismet', 'vaultpress', + 'wordads', ); + $plan['class'] = 'premium'; } // Define what paid modules are supported by professional plans @@ -1261,7 +1292,10 @@ class Jetpack { 'akismet', 'vaultpress', 'seo-tools', + 'google-analytics', + 'wordads', ); + $plan['class'] = 'business'; } // Make sure we have an array here in the event database data is stale @@ -1300,11 +1334,10 @@ class Jetpack { if ( defined( 'JETPACK_DEV_DEBUG' ) ) { $development_mode = JETPACK_DEV_DEBUG; + } elseif ( $site_url = site_url() ) { + $development_mode = false === strpos( $site_url, '.' ); } - elseif ( site_url() && false === strpos( site_url(), '.' ) ) { - $development_mode = true; - } /** * Filters Jetpack's development mode. * @@ -2292,7 +2325,7 @@ class Jetpack { */ public static function get_active_modules() { $active = Jetpack_Options::get_option( 'active_modules' ); - + if ( ! is_array( $active ) ) { $active = array(); } @@ -2527,7 +2560,6 @@ class Jetpack { if ( 'protect' === $module ) { include_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php'; if ( ! jetpack_protect_get_ip() ) { - error_log( 'hello' ); Jetpack::state( 'message', 'protect_misconfigured_ip' ); return false; } @@ -2750,6 +2782,7 @@ p { // If the site is in an IDC because sync is not allowed, // let's make sure to not disconnect the production site. if ( ! self::validate_sync_error_idc_option() ) { + JetpackTracking::record_user_event( 'disconnect_site', array() ); Jetpack::load_xml_rpc_client(); $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.deregister' ); @@ -3147,13 +3180,20 @@ p { function add_remote_request_handlers() { add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) ); + add_action( 'wp_ajax_nopriv_jetpack_update_file', array( $this, 'remote_request_handlers' ) ); } function remote_request_handlers() { + $action = current_filter(); + switch ( current_filter() ) { case 'wp_ajax_nopriv_jetpack_upload_file' : $response = $this->upload_handler(); break; + + case 'wp_ajax_nopriv_jetpack_update_file' : + $response = $this->upload_handler( true ); + break; default : $response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 ); break; @@ -3184,7 +3224,16 @@ p { die( json_encode( (object) $response ) ); } - function upload_handler() { + /** + * Uploads a file gotten from the global $_FILES. + * If `$update_media_item` is true and `post_id` is defined + * the attachment file of the media item (gotten through of the post_id) + * will be updated instead of add a new one. + * + * @param boolean $update_media_item - update media attachment + * @return array - An array describing the uploadind files process + */ + function upload_handler( $update_media_item = false ) { if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 ); } @@ -3239,6 +3288,37 @@ p { if ( ! current_user_can( 'edit_post', $post_id ) ) { $post_id = 0; } + + if ( $update_media_item ) { + if ( ! isset( $post_id ) || $post_id === 0 ) { + return new Jetpack_Error( 'invalid_input', 'Media ID must be defined.', 400 ); + } + + $media_array = $_FILES['media']; + + $file_array['name'] = $media_array['name'][0]; + $file_array['type'] = $media_array['type'][0]; + $file_array['tmp_name'] = $media_array['tmp_name'][0]; + $file_array['error'] = $media_array['error'][0]; + $file_array['size'] = $media_array['size'][0]; + + $edited_media_item = Jetpack_Media::edit_media_file( $post_id, $file_array ); + + if ( is_wp_error( $edited_media_item ) ) { + return $edited_media_item; + } + + $response = (object) array( + 'id' => (string) $post_id, + 'file' => (string) $edited_media_item->post_title, + 'url' => (string) wp_get_attachment_url( $post_id ), + 'type' => (string) $edited_media_item->post_mime_type, + 'meta' => (array) wp_get_attachment_metadata( $post_id ), + ); + + return (array) array( $response ); + } + $attachment_id = media_handle_upload( '.jetpack.upload.', $post_id, @@ -4444,7 +4524,7 @@ p { public function get_remote_query_timeout_limit() { $timeout = (int) ini_get( 'max_execution_time' ); if ( ! $timeout ) // Ensure exec time set in php.ini - $timeout = 30; + $timeout = 30; return intval( $timeout / 2 ); } @@ -4454,47 +4534,47 @@ p { * verifies it worked properly. * * @since 2.6 - * @return true or Jetpack_Error + * @return string|Jetpack_Error A JSON object on success or Jetpack_Error on failures **/ public function validate_remote_register_response( $response ) { - if ( is_wp_error( $response ) ) { + if ( is_wp_error( $response ) ) { return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() ); } $code = wp_remote_retrieve_response_code( $response ); $entity = wp_remote_retrieve_body( $response ); if ( $entity ) - $json = json_decode( $entity ); + $registration_response = json_decode( $entity ); else - $json = false; + $registration_response = false; $code_type = intval( $code / 100 ); if ( 5 == $code_type ) { return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); } elseif ( 408 == $code ) { return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); - } elseif ( ! empty( $json->error ) ) { - if ( 'xml_rpc-32700' == $json->error && ! function_exists( 'xml_parser_create' ) ) { + } elseif ( ! empty( $registration_response->error ) ) { + if ( 'xml_rpc-32700' == $registration_response->error && ! function_exists( 'xml_parser_create' ) ) { $error_description = __( "PHP's XML extension is not available. Jetpack requires the XML extension to communicate with WordPress.com. Please contact your hosting provider to enable PHP's XML extension.", 'jetpack' ); } else { - $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : ''; + $error_description = isset( $registration_response->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $registration_response->error_description ) : ''; } - - return new Jetpack_Error( (string) $json->error, $error_description, $code ); + + return new Jetpack_Error( (string) $registration_response->error, $error_description, $code ); } elseif ( 200 != $code ) { return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); } // Jetpack ID error block - if ( empty( $json->jetpack_id ) ) { + if ( empty( $registration_response->jetpack_id ) ) { return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity ); - } elseif ( ! is_scalar( $json->jetpack_id ) ) { + } elseif ( ! is_scalar( $registration_response->jetpack_id ) ) { return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity ); - } elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) { + } elseif ( preg_match( '/[^0-9]/', $registration_response->jetpack_id ) ) { return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity ); } - return true; + return $registration_response; } /** * @return bool|WP_Error @@ -4540,35 +4620,28 @@ p { ); $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ) ), $args, true ); - // Make sure the response is valid and does not contain any Jetpack errors - $valid_response = Jetpack::init()->validate_remote_register_response( $response ); - if( is_wp_error( $valid_response ) || !$valid_response ) { - return $valid_response; + $registration_details = Jetpack::init()->validate_remote_register_response( $response ); + if ( is_wp_error( $registration_details ) ) { + return $registration_details; + } elseif ( ! $registration_details ) { + return new Jetpack_Error( 'unknown_error', __( 'Unknown error registering your Jetpack site', 'jetpack' ), wp_remote_retrieve_response_code( $response ) ); } - // Grab the response values to work with - $code = wp_remote_retrieve_response_code( $response ); - $entity = wp_remote_retrieve_body( $response ); - - if ( $entity ) - $json = json_decode( $entity ); - else - $json = false; - - if ( empty( $json->jetpack_secret ) || ! is_string( $json->jetpack_secret ) ) - return new Jetpack_Error( 'jetpack_secret', '', $code ); + if ( empty( $registration_details->jetpack_secret ) || ! is_string( $registration_details->jetpack_secret ) ) { + return new Jetpack_Error( 'jetpack_secret', '', wp_remote_retrieve_response_code( $response ) ); + } - if ( isset( $json->jetpack_public ) ) { - $jetpack_public = (int) $json->jetpack_public; + if ( isset( $registration_details->jetpack_public ) ) { + $jetpack_public = (int) $registration_details->jetpack_public; } else { $jetpack_public = false; } Jetpack_Options::update_options( array( - 'id' => (int) $json->jetpack_id, - 'blog_token' => (string) $json->jetpack_secret, + 'id' => (int) $registration_details->jetpack_id, + 'blog_token' => (string) $registration_details->jetpack_secret, 'public' => $jetpack_public, ) ); @@ -4582,7 +4655,7 @@ p { * @param string $json->jetpack_secret Jetpack Blog Token. * @param int|bool $jetpack_public Is the site public. */ - do_action( 'jetpack_site_registered', $json->jetpack_id, $json->jetpack_secret, $jetpack_public ); + do_action( 'jetpack_site_registered', $registration_details->jetpack_id, $registration_details->jetpack_secret, $jetpack_public ); // Initialize Jump Start for the first and only time. if ( ! Jetpack_Options::get_option( 'jumpstart' ) ) { @@ -4840,22 +4913,23 @@ p { } if ( - false === $verified || - ! isset( $verified['type'] ) || - 'user' !== $verified['type'] || - empty( $verified['user_id'] ) + $verified && + isset( $verified['type'] ) && + 'user' === $verified['type'] && + ! empty( $verified['user_id'] ) ) { - $this->rest_authentication_status = new WP_Error( - 'rest_invalid_signature', - __( 'The request is not signed correctly.', 'jetpack' ), - array( 'status' => 400 ) - ); - return null; + // Authentication successful. + $this->rest_authentication_status = true; + return $verified['user_id']; } - // Authentication successful. - $this->rest_authentication_status = true; - return $verified['user_id']; + // Something else went wrong. Probably a signature error. + $this->rest_authentication_status = new WP_Error( + 'rest_invalid_signature', + __( 'The request is not signed correctly.', 'jetpack' ), + array( 'status' => 400 ) + ); + return null; } /** @@ -5254,11 +5328,24 @@ p { ); } - // Verifies the request by checking the signature - function verify_json_api_authorization_request() { + + /** + * Verifies the request by checking the signature + * + * @since 4.6.0 Method was updated to use `$_REQUEST` instead of `$_GET` and `$_POST`. Method also updated to allow + * passing in an `$environment` argument that overrides `$_REQUEST`. This was useful for integrating with SSO. + * + * @param null|array $environment + */ + function verify_json_api_authorization_request( $environment = null ) { require_once JETPACK__PLUGIN_DIR . 'class.jetpack-signature.php'; - $token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER ); + $environment = is_null( $environment ) + ? $_REQUEST + : $environment; + + list( $envToken, $envVersion, $envUserId ) = explode( ':', $environment['token'] ); + $token = Jetpack_Data::get_access_token( $envUserId ); if ( ! $token || empty( $token->secret ) ) { wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack' ) ); } @@ -5267,8 +5354,17 @@ p { $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack_Options::get_option( 'time_diff' ) ); - if ( isset( $_POST['jetpack_json_api_original_query'] ) ) { - $signature = $jetpack_signature->sign_request( $_GET['token'], $_GET['timestamp'], $_GET['nonce'], '', 'GET', $_POST['jetpack_json_api_original_query'], null, true ); + if ( isset( $environment['jetpack_json_api_original_query'] ) ) { + $signature = $jetpack_signature->sign_request( + $environment['token'], + $environment['timestamp'], + $environment['nonce'], + '', + 'GET', + $environment['jetpack_json_api_original_query'], + null, + true + ); } else { $signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) ); } @@ -5277,11 +5373,11 @@ p { wp_die( $die_error ); } else if ( is_wp_error( $signature ) ) { wp_die( $die_error ); - } else if ( ! hash_equals( $signature, $_GET['signature'] ) ) { + } else if ( ! hash_equals( $signature, $environment['signature'] ) ) { if ( is_ssl() ) { // If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well $signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) ); - if ( ! $signature || is_wp_error( $signature ) || ! hash_equals( $signature, $_GET['signature'] ) ) { + if ( ! $signature || is_wp_error( $signature ) || ! hash_equals( $signature, $environment['signature'] ) ) { wp_die( $die_error ); } } else { @@ -5289,8 +5385,8 @@ p { } } - $timestamp = (int) $_GET['timestamp']; - $nonce = stripslashes( (string) $_GET['nonce'] ); + $timestamp = (int) $environment['timestamp']; + $nonce = stripslashes( (string) $environment['nonce'] ); if ( ! $this->add_nonce( $timestamp, $nonce ) ) { // De-nonce the nonce, at least for 5 minutes. @@ -5301,7 +5397,7 @@ p { } } - $data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) ); + $data = json_decode( base64_decode( stripslashes( $environment['data'] ) ) ); $data_filters = array( 'state' => 'opaque', 'client_id' => 'int', @@ -5358,45 +5454,6 @@ p { } /** - * Centralize the function here until it gets added to core. - * - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param bool $force_display Whether to force it to return an avatar even if show_avatars is disabled - * - * @return array First element is the URL, second is the class. - */ - public static function get_avatar_url( $id_or_email, $size = 96, $default = '', $force_display = false ) { - // Don't bother adding the __return_true filter if it's already there. - $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' ); - - if ( $force_display && ! $has_filter ) - add_filter( 'pre_option_show_avatars', '__return_true' ); - - $avatar = get_avatar( $id_or_email, $size, $default ); - - if ( $force_display && ! $has_filter ) - remove_filter( 'pre_option_show_avatars', '__return_true' ); - - // If no data, fail out. - if ( is_wp_error( $avatar ) || ! $avatar ) - return array( null, null ); - - // Pull out the URL. If it's not there, fail out. - if ( ! preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $url_matches ) ) - return array( null, null ); - $url = wp_specialchars_decode( $url_matches[1], ENT_QUOTES ); - - // Pull out the class, but it's not a big deal if it's missing. - $class = ''; - if ( preg_match( '/class=["\']([^"\']+)["\']/', $avatar, $class_matches ) ) - $class = wp_specialchars_decode( $class_matches[1], ENT_QUOTES ); - - return array( $url, $class ); - } - - /** * Pings the WordPress.com Mirror Site for the specified options. * * @param string|array $option_names The option names to request from the WordPress.com Mirror Site |