summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/class.jetpack.php')
-rw-r--r--plugins/jetpack/class.jetpack.php275
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