/** * Synchronize connected user role changes */ static function user_role_change($user_id) { if (Jetpack::is_active() && Jetpack::is_user_connected($user_id)) { $current_user_id = get_current_user_id(); wp_set_current_user($user_id); $role = Jetpack::translate_current_user_to_role(); $signed_role = Jetpack::sign_role($role); wp_set_current_user($current_user_id); $master_token = Jetpack_Data::get_access_token(JETPACK_MASTER_USER); $master_user_id = absint($master_token->external_user_id); if (!$master_user_id) { return; } // this shouldn't happen Jetpack::xmlrpc_async_call('jetpack.updateRole', $user_id, $signed_role); //@todo retry on failure //try to choose a new master if we're demoting the current one if ($user_id == $master_user_id && 'administrator' != $role) { $query = new WP_User_Query(array('fields' => array('id'), 'role' => 'administrator', 'orderby' => 'id', 'exclude' => array($master_user_id))); $new_master = false; foreach ($query->results as $result) { $uid = absint($result->id); if ($uid && Jetpack::is_user_connected($uid)) { $new_master = $uid; break; } } if ($new_master) { Jetpack_Options::update_option('master_user', $new_master); } // else disconnect..? } } }
function check_user_connection() { $user_token = Jetpack_Data::get_access_token(get_current_user_id()); $is_user_connected = $user_token && !is_wp_error($user_token); // If the user is already connected via Jetpack, then we're good if ($is_user_connected) { return true; } return false; }
function force_user_connection() { global $current_user; $user_token = Jetpack_Data::get_access_token($current_user->ID); $is_user_connected = $user_token && !is_wp_error($user_token); // If the user is already connected via Jetpack, then we're good if ($is_user_connected) { return; } // If they're not connected, then remove the Publicize UI and tell them they need to connect first global $publicize_ui; remove_action('pre_admin_screen_sharing', array($publicize_ui, 'admin_page')); Jetpack::init()->admin_styles(); add_action('pre_admin_screen_sharing', array($this, 'admin_page_warning'), 1); }
function page_render() { // Handle redirects to configuration pages if (!empty($_GET['configure'])) { return $this->render_nojs_configurable(); } global $current_user; $is_connected = Jetpack::is_active(); $user_token = Jetpack_Data::get_access_token($current_user->ID); $is_user_connected = $user_token && !is_wp_error($user_token); $is_master_user = $current_user->ID == Jetpack_Options::get_option('master_user'); if (Jetpack::is_development_mode()) { $is_connected = true; $is_user_connected = true; $is_master_user = false; } // Set template data for the admin page template $data = array('is_connected' => $is_connected, 'is_user_connected' => $is_user_connected, 'is_master_user' => $is_master_user); Jetpack::init()->load_view('admin/admin-page.php', $data); }
function jetpack_my_jetpack_change_user() { if (!isset($_POST['_my_jetpack_nonce']) || !wp_verify_nonce($_POST['_my_jetpack_nonce'], 'jetpack_change_primary_user')) { wp_die(__('Failed permissions, please try again.', 'jetpack')); exit; } if (isset($_POST['jetpack-new-master'])) { $old_master_user = Jetpack_Options::get_option('master_user'); $new_master_user = $_POST['jetpack-new-master']; $user_token = Jetpack_Data::get_access_token($new_master_user); $is_user_connected = $user_token && !is_wp_error($user_token); if (current_user_can('manage_options') && $is_user_connected) { Jetpack::log('switch_master_user', array('old_master' => $old_master_user, 'new_master' => $new_master_user)); Jetpack_Options::update_option('master_user', $new_master_user); Jetpack::state('message', 'switch_master'); //My Jetpack primary user successfully changed, send to MC Stats Jetpack::init()->stat('admin', 'change-primary-successful'); Jetpack::init()->do_stats('server_side'); // Change the blog owner dotcom side $this->wpcom_switch_blog_owner($new_master_user); } } }
function verify_json_api_authorization_request() { require_once JETPACK__PLUGIN_DIR . 'class.jetpack-signature.php'; $token = Jetpack_Data::get_access_token(JETPACK_MASTER_USER); if (!$token || empty($token->secret)) { wp_die(__('You must connect your Jetpack plugin to WordPress.com to use this feature.', 'jetpack')); } $die_error = __('Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack'); $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); } else { $signature = $jetpack_signature->sign_current_request(array('body' => null, 'method' => 'GET')); } if (!$signature) { wp_die($die_error); } else { if (is_wp_error($signature)) { wp_die($die_error); } else { if ($signature !== $_GET['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) || $signature !== $_GET['signature']) { wp_die($die_error); } } else { wp_die($die_error); } } } } $timestamp = (int) $_GET['timestamp']; $nonce = stripslashes((string) $_GET['nonce']); if (!$this->add_nonce($timestamp, $nonce)) { // De-nonce the nonce, at least for 5 minutes. // We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed) $old_nonce_time = get_option("jetpack_nonce_{$timestamp}_{$nonce}"); if ($old_nonce_time < time() - 300) { wp_die(__('The authorization process expired. Please go back and try again.', 'jetpack')); } } $data = json_decode(base64_decode(stripslashes($_GET['data']))); $data_filters = array('state' => 'opaque', 'client_id' => 'int', 'client_title' => 'string', 'client_image' => 'url'); foreach ($data_filters as $key => $sanitation) { if (!isset($data->{$key})) { wp_die($die_error); } switch ($sanitation) { case 'int': $this->json_api_authorization_request[$key] = (int) $data->{$key}; break; case 'opaque': $this->json_api_authorization_request[$key] = (string) $data->{$key}; break; case 'string': $this->json_api_authorization_request[$key] = wp_kses((string) $data->{$key}, array()); break; case 'url': $this->json_api_authorization_request[$key] = esc_url_raw((string) $data->{$key}); break; } } if (empty($this->json_api_authorization_request['client_id'])) { wp_die($die_error); } }
/** * @return object|WP_Error */ function get_token($data) { $jetpack = Jetpack::init(); $role = $jetpack->translate_current_user_to_role(); if (!$role) { return new Jetpack_Error('role', __('An administrator for this blog must set up the Jetpack connection.', 'jetpack')); } $client_secret = Jetpack_Data::get_access_token(0); if (!$client_secret) { return new Jetpack_Error('client_secret', __('You need to register your Jetpack before connecting it.', 'jetpack')); } $body = array('client_id' => Jetpack::get_option('id'), 'client_secret' => $client_secret->secret, 'grant_type' => 'authorization_code', 'code' => $data['code'], 'redirect_uri' => add_query_arg(array('action' => 'authorize', '_wpnonce' => wp_create_nonce("jetpack-authorize_{$role}")), menu_page_url('jetpack', false))); $args = array('method' => 'POST', 'body' => $body, 'headers' => array('Accept' => 'application/json')); $response = Jetpack_Client::_wp_remote_request(Jetpack::fix_url_for_bad_hosts(Jetpack::api_url('token'), $args), $args); if (is_wp_error($response)) { return new Jetpack_Error('token_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); } else { $json = false; } if (200 != $code || !empty($json->error)) { if (empty($json->error)) { return new Jetpack_Error('unknown', '', $code); } $error_description = isset($json->error_description) ? sprintf(__('Error Details: %s', 'jetpack'), (string) $json->error_description) : ''; return new Jetpack_Error((string) $json->error, $error_description, $code); } if (empty($json->access_token) || !is_scalar($json->access_token)) { return new Jetpack_Error('access_token', '', $code); } if (empty($json->token_type) || 'X_JETPACK' != strtoupper($json->token_type)) { return new Jetpack_Error('token_type', '', $code); } if (empty($json->scope)) { return new Jetpack_Error('scope', 'No Scope', $code); } @(list($role, $hmac) = explode(':', $json->scope)); if (empty($role) || empty($hmac)) { return new Jetpack_Error('scope', 'Malformed Scope', $code); } if ($jetpack->sign_role($role) !== $json->scope) { return new Jetpack_Error('scope', 'Invalid Scope', $code); } if (!($cap = $jetpack->translate_role_to_cap($role))) { return new Jetpack_Error('scope', 'No Cap', $code); } if (!current_user_can($cap)) { return new Jetpack_Error('scope', 'current_user_cannot', $code); } return (string) $json->access_token; }
/** * Returns true if the provided user is the Jetpack connection owner. */ function is_connection_owner($user_id = false) { if (!$user_id) { $user_id = get_current_user_id(); } $user_token = Jetpack_Data::get_access_token(JETPACK_MASTER_USER); return $user_token && is_object($user_token) && isset($user_token->external_user_id) && $user_id === $user_token->external_user_id; }
/** * Makes an authorized remote request using Jetpack_Signature * * @return array|WP_Error WP HTTP response on success */ public static function remote_request($args, $body = null) { $defaults = array('url' => '', 'user_id' => 0, 'blog_id' => 0, 'auth_location' => JETPACK_CLIENT__AUTH_LOCATION, 'method' => 'POST', 'timeout' => 10, 'redirection' => 0); $args = wp_parse_args($args, $defaults); $args['blog_id'] = (int) $args['blog_id']; if ('header' != $args['auth_location']) { $args['auth_location'] = 'query_string'; } $token = Jetpack_Data::get_access_token($args['user_id']); if (!$token) { return new Jetpack_Error('missing_token'); } $method = strtoupper($args['method']); $timeout = intval($args['timeout']); $redirection = $args['redirection']; $request = compact('method', 'body', 'timeout', 'redirection'); @(list($token_key, $secret) = explode('.', $token->secret)); if (empty($token) || empty($secret)) { return new Jetpack_Error('malformed_token'); } $token_key = sprintf('%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id); require_once dirname(__FILE__) . '/class.jetpack-signature.php'; $time_diff = (int) Jetpack_Options::get_option('time_diff'); $jetpack_signature = new Jetpack_Signature($token->secret, $time_diff); $timestamp = time() + $time_diff; $nonce = wp_generate_password(10, false); // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing if (is_null($body)) { $body_hash = ''; } else { if (!is_string($body)) { return new Jetpack_Error('invalid_body', 'Body is malformed.'); } $body_hash = jetpack_sha1_base64($body); } $auth = array('token' => $token_key, 'timestamp' => $timestamp, 'nonce' => $nonce, 'body-hash' => $body_hash); if (false !== strpos($args['url'], 'xmlrpc.php')) { $url_args = array('for' => 'jetpack', 'wpcom_blog_id' => Jetpack_Options::get_option('id')); } else { $url_args = array(); } if ('header' != $args['auth_location']) { $url_args += $auth; } $url = add_query_arg(urlencode_deep($url_args), $args['url']); $url = Jetpack::fix_url_for_bad_hosts($url); $signature = $jetpack_signature->sign_request($token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false); if (!$signature || is_wp_error($signature)) { return $signature; } // Send an Authorization header so various caches/proxies do the right thing $auth['signature'] = $signature; $auth['version'] = JETPACK__VERSION; $header_pieces = array(); foreach ($auth as $key => $value) { $header_pieces[] = sprintf('%s="%s"', $key, $value); } $request['headers'] = array('Authorization' => "X_JETPACK " . join(' ', $header_pieces)); if ('header' != $args['auth_location']) { $url = add_query_arg('signature', urlencode($signature), $url); } return Jetpack_Client::_wp_remote_request($url, $request); }
function json_api($args = array()) { $json_api_args = $args[0]; $verify_api_user_args = $args[1]; $method = (string) $json_api_args[0]; $url = (string) $json_api_args[1]; $post_body = is_null($json_api_args[2]) ? null : (string) $json_api_args[2]; $my_id = (int) $json_api_args[3]; $user_details = (array) $json_api_args[4]; if (!$verify_api_user_args) { $user_id = 0; } elseif ('internal' === $verify_api_user_args[0]) { $user_id = (int) $verify_api_user_args[1]; if ($user_id) { $user = get_user_by('id', $user_id); if (!$user || is_wp_error($user)) { return false; } } } else { $user_id = call_user_func(array($this, 'test_api_user_code'), $verify_api_user_args); if (!$user_id) { return false; } } /* debugging error_log( "-- begin json api via jetpack debugging -- " ); error_log( "METHOD: $method" ); error_log( "URL: $url" ); error_log( "POST BODY: $post_body" ); error_log( "MY JETPACK ID: $my_id" ); error_log( "VERIFY_ARGS: " . print_r( $verify_api_user_args, 1 ) ); error_log( "VERIFIED USER_ID: " . (int) $user_id ); error_log( "-- end json api via jetpack debugging -- " ); */ $old_user = wp_get_current_user(); wp_set_current_user($user_id); $token = Jetpack_Data::get_access_token(get_current_user_id()); if (!$token || is_wp_error($token)) { return false; } define('REST_API_REQUEST', true); define('WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1'); // needed? require_once ABSPATH . 'wp-admin/includes/admin.php'; require_once dirname(__FILE__) . '/class.json-api.php'; $api = WPCOM_JSON_API::init($method, $url, $post_body); $api->token_details['user'] = $user_details; require_once dirname(__FILE__) . '/class.json-api-endpoints.php'; $display_errors = ini_set('display_errors', 0); ob_start(); $content_type = $api->serve(false); $output = ob_get_clean(); ini_set('display_errors', $display_errors); $nonce = wp_generate_password(10, false); $hmac = hash_hmac('md5', $nonce . $output, $token->secret); wp_set_current_user(isset($old_user->ID) ? $old_user->ID : 0); return array((string) $output, (string) $nonce, (string) $hmac); }
function admin_page() { global $current_user; $is_connected = Jetpack::is_active(); $user_token = Jetpack_Data::get_access_token($current_user->ID); $is_user_connected = $user_token && !is_wp_error($user_token); $is_master_user = $current_user->ID == Jetpack_Options::get_option('master_user'); if (Jetpack::is_development_mode()) { $is_connected = true; $is_user_connected = true; $is_master_user = false; } $this->admin_page_top(); ?> <div class="masthead <?php if (!$is_connected) { echo 'hasbutton'; } ?> "> <?php if (isset($_GET['jetpack-notice']) && 'dismiss' == $_GET['jetpack-notice']) { ?> <div id="message" class="error"> <p><?php esc_html_e('Jetpack is network activated and notices can not be dismissed.', 'jetpack'); ?> </p> </div> <?php } ?> <?php do_action('jetpack_notices'); ?> <h1><?php esc_html_e('Supercharge your self-hosted site with a suite of the most powerful WordPress.com features.', 'jetpack'); ?> </h1> <?php if (!$is_connected && current_user_can('jetpack_connect')) { ?> <a href="<?php echo $this->jetpack->build_connect_url(); ?> " class="download-jetpack"><?php esc_html_e('Connect to Get Started', 'jetpack'); ?> </a> <?php } elseif (!$is_user_connected && current_user_can('jetpack_connect_user')) { ?> <a href="<?php echo $this->jetpack->build_connect_url(); ?> " class="download-jetpack"><?php esc_html_e('Link your account to WordPress.com', 'jetpack'); ?> </a> <?php } ?> <div class="flyby"> <svg class="flyer" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="80px" height="87px" viewBox="0 0 80 87" enable-background="new 0 0 80 87" xml:space="preserve"> <polygon class="eye" fill="#518d2a" points="41.187,17.081 46.769,11.292 50.984,15.306"/> <path class="body" fill="#518d2a" d="M38.032,47.3l4.973-5.157l7.597,1.996l0.878-0.91l0.761-0.789l-0.688-2.838l-0.972-0.926l-1.858,1.926 l-2.206-2.1l3.803-3.944l0.09-3.872L80,0L61.201,10.382L60.2,15.976l-5.674,1.145l-8.09-7.702L34.282,22.024l8.828-1.109 l2.068,2.929l-4.996,0.655l-3.467,3.595l0.166-4.469l-4.486,0.355L21.248,35.539l-0.441,4.206l-2.282,2.366l-2.04,6.961 L27.69,37.453l4.693,1.442l-2.223,2.306l-4.912,0.095l-7.39,22.292l-8.06,3.848l-2.408,9.811l-3.343-0.739L0,86.739l30.601-31.733 l8.867,2.507l-7.782,8.07l-1.496-0.616l-0.317-2.623l-7.197,7.463l11.445-2.604l16.413-7.999L38.032,47.3z M42.774,16.143 l3.774-3.914l2.85,2.713L42.774,16.143z"/> </svg> <svg class="flyer" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="80px" height="87px" viewBox="0 0 80 87" enable-background="new 0 0 80 87" xml:space="preserve"> <polygon class="eye" fill="#518d2a" points="41.187,17.081 46.769,11.292 50.984,15.306 "/> <path class="body" fill="#518d2a" d="M38.032,47.3l4.973-5.157l7.597,1.996l0.878-0.91l0.761-0.789l-0.688-2.838l-0.972-0.926l-1.858,1.926 l-2.206-2.1l3.803-3.944l0.09-3.872L80,0L61.201,10.382L60.2,15.976l-5.674,1.145l-8.09-7.702L34.282,22.024l8.828-1.109 l2.068,2.929l-4.996,0.655l-3.467,3.595l0.166-4.469l-4.486,0.355L21.248,35.539l-0.441,4.206l-2.282,2.366l-2.04,6.961 L27.69,37.453l4.693,1.442l-2.223,2.306l-4.912,0.095l-7.39,22.292l-8.06,3.848l-2.408,9.811l-3.343-0.739L0,86.739l30.601-31.733 l8.867,2.507l-7.782,8.07l-1.496-0.616l-0.317-2.623l-7.197,7.463l11.445-2.604l16.413-7.999L38.032,47.3z M42.774,16.143 l3.774-3.914l2.85,2.713L42.774,16.143z"/> </svg> <svg class="flyer" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="80px" height="87px" viewBox="0 0 80 87" enable-background="new 0 0 80 87" xml:space="preserve"> <polygon class="eye" fill="#518d2a" points="41.187,17.081 46.769,11.292 50.984,15.306 "/> <path class="body" fill="#518d2a" d="M38.032,47.3l4.973-5.157l7.597,1.996l0.878-0.91l0.761-0.789l-0.688-2.838l-0.972-0.926l-1.858,1.926 l-2.206-2.1l3.803-3.944l0.09-3.872L80,0L61.201,10.382L60.2,15.976l-5.674,1.145l-8.09-7.702L34.282,22.024l8.828-1.109 l2.068,2.929l-4.996,0.655l-3.467,3.595l0.166-4.469l-4.486,0.355L21.248,35.539l-0.441,4.206l-2.282,2.366l-2.04,6.961 L27.69,37.453l4.693,1.442l-2.223,2.306l-4.912,0.095l-7.39,22.292l-8.06,3.848l-2.408,9.811l-3.343-0.739L0,86.739l30.601-31.733 l8.867,2.507l-7.782,8.07l-1.496-0.616l-0.317-2.623l-7.197,7.463l11.445-2.604l16.413-7.999L38.032,47.3z M42.774,16.143 l3.774-3.914l2.85,2.713L42.774,16.143z"/> </svg> </div> <div class="subhead"> <?php if (Jetpack::is_development_mode()) { ?> <h2><?php _e('Jetpack is in local development mode.', 'jetpack'); ?> </h2> <?php } elseif ($is_connected) { ?> <h2><?php _e("You're successfully connected to Jetpack!", 'jetpack'); ?> </h2> <?php } else { ?> <h2><?php _e('Once you’ve connected Jetpack, you’ll get access to all the delightful features below.', 'jetpack'); ?> </h2> <?php } ?> </div> </div><!-- .masthead --> <div class="featured"> <h2><?php _e('Jetpack team favorites', 'jetpack'); ?> </h2> <div class="features"> <div class="feature"> <a href="http://jetpack.me/support/custom-css/" data-name="Custom CSS" class="f-img"><div class="feature-img custom-css"></div></a> <a href="http://jetpack.me/support/custom-css/" data-name="Custom CSS" class="feature-description"> <h3><?php _e('Custom CSS', 'jetpack'); ?> </h3> <p><?php _e('Customize the look of your site, without modifying your theme.', 'jetpack'); ?> </p> </a> </div> <div class="feature"> <a href="http://jetpack.me/support/sso/" data-name="Jetpack Single Sign On" class="f-img"><div class="feature-img wordpress-connect no-border"></div></a> <a href="http://jetpack.me/support/sso/" data-name="Jetpack Single Sign On" class="feature-description"> <h3><?php _e('Single Sign On', 'jetpack'); ?> </h3> <p><?php _e('Let users log in through WordPress.com with one click.', 'jetpack'); ?> </p> </a> </div> <div class="feature"> <a href="http://jetpack.me/support/wordpress-com-stats/" data-name="WordPress.com Stats" class="f-img"><div class="feature-img wordpress-stats"></div></a> <a href="http://jetpack.me/support/wordpress-com-stats/" data-name="WordPress.com Stats" class="feature-description"> <h3><?php _e('WordPress.com Stats', 'jetpack'); ?> </h3> <p><?php _e('Simple, concise site stats with no additional load on your server.', 'jetpack'); ?> </p> </a> </div> </div> </div><!-- .featured --> <div class="page-content about"> <div class="module-grid"> <h2><?php esc_html_e('Jetpack features', 'jetpack'); ?> </h2> <!-- form with search and filters --> <form id="module-search"> <input type="text" id="jetpack-search" class="module-search" placeholder="<?php esc_attr_e('Search the Jetpack features', 'jetpack'); ?> " /><label for="jetpack-search"><?php esc_html_e('Search', 'jetpack'); ?> </label> </form> <div class="jp-filter" id="jp-filters"> <a href="#" id="newest" data-filter="introduced" class="selected"><?php esc_html_e('Newest', 'jetpack'); ?> </a> <a href="#" id="category" data-filter="cat"><?php _e('Category', 'jetpack'); ?> </a> <a href="#" id="alphabetical" data-filter="name"><?php esc_html_e('Alphabetical', 'jetpack'); ?> </a> </div> <div class="modules"></div> <a href="#" class="load-more jp-button"><?php esc_html_e('Load more', 'jetpack'); ?> </a> </div><!-- .module-grid --></div><!-- .page --> <?php $this->admin_page_bottom(); }
function json_api($args = array()) { $json_api_args = $args[0]; $verify_api_user_args = $args[1]; $method = (string) $json_api_args[0]; $url = (string) $json_api_args[1]; $post_body = is_null($json_api_args[2]) ? null : (string) $json_api_args[2]; $user_details = (array) $json_api_args[4]; $locale = (string) $json_api_args[5]; if (!$verify_api_user_args) { $user_id = 0; } elseif ('internal' === $verify_api_user_args[0]) { $user_id = (int) $verify_api_user_args[1]; if ($user_id) { $user = get_user_by('id', $user_id); if (!$user || is_wp_error($user)) { return false; } } } else { $user_id = call_user_func(array($this, 'test_api_user_code'), $verify_api_user_args); if (!$user_id) { return false; } } /* debugging error_log( "-- begin json api via jetpack debugging -- " ); error_log( "METHOD: $method" ); error_log( "URL: $url" ); error_log( "POST BODY: $post_body" ); error_log( "VERIFY_ARGS: " . print_r( $verify_api_user_args, 1 ) ); error_log( "VERIFIED USER_ID: " . (int) $user_id ); error_log( "-- end json api via jetpack debugging -- " ); */ if ('en' !== $locale) { // .org mo files are named slightly different from .com, and all we have is this the locale -- try to guess them. $new_locale = $locale; if (strpos($locale, '-') !== false) { $pieces = explode('-', $locale); $new_locale = $locale_pieces[0]; $new_locale .= !empty($locale_pieces[1]) ? '_' . strtoupper($locale_pieces[1]) : ''; } else { // .com might pass 'fr' because thats what our language files are named as, where core seems // to do fr_FR - so try that if we don't think we can load the file. if (!file_exists(WP_LANG_DIR . '/' . $locale . '.mo')) { $new_locale = $locale . '_' . strtoupper($locale); } } if (file_exists(WP_LANG_DIR . '/' . $new_locale . '.mo')) { unload_textdomain('default'); load_textdomain('default', WP_LANG_DIR . '/' . $new_locale . '.mo'); } } $old_user = wp_get_current_user(); wp_set_current_user($user_id); $token = Jetpack_Data::get_access_token(get_current_user_id()); if (!$token || is_wp_error($token)) { return false; } define('REST_API_REQUEST', true); define('WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1'); // needed? require_once ABSPATH . 'wp-admin/includes/admin.php'; require_once JETPACK__PLUGIN_DIR . 'class.json-api.php'; $api = WPCOM_JSON_API::init($method, $url, $post_body); $api->token_details['user'] = $user_details; require_once JETPACK__PLUGIN_DIR . 'class.json-api-endpoints.php'; $display_errors = ini_set('display_errors', 0); ob_start(); $content_type = $api->serve(false); $output = ob_get_clean(); ini_set('display_errors', $display_errors); $nonce = wp_generate_password(10, false); $hmac = hash_hmac('md5', $nonce . $output, $token->secret); wp_set_current_user(isset($old_user->ID) ? $old_user->ID : 0); return array((string) $output, (string) $nonce, (string) $hmac); }
/** * Stylized JP header formatting * * @since 2.9 */ function network_admin_page_header() { global $current_user; $is_connected = Jetpack::is_active(); $user_token = Jetpack_Data::get_access_token($current_user->ID); $is_user_connected = $user_token && !is_wp_error($user_token); $is_master_user = $current_user->ID == Jetpack_Options::get_option('master_user'); require_once 'views/admin/network-admin-header.php'; }
protected function authorization_header() { $token = Jetpack_Data::get_access_token(0); $token = apply_filters('wc_connect_jetpack_access_token', $token); if (!$token || empty($token->secret)) { return new WP_Error('missing_token', 'Unable to send request to Connect for WooCommerce server. Jetpack Token is missing'); } if (false === strpos($token->secret, '.')) { return new WP_Error('invalid_token', 'Unable to send request to Connect for WooCommerce server. Jetpack Token is malformed.'); } list($token_key, $token_secret) = explode('.', $token->secret); $token_key = sprintf('%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id); $time_diff = (int) Jetpack_Options::get_option('time_diff'); $timestamp = time() + $time_diff; $nonce = wp_generate_password(10, false); $signature = $this->request_signature($token_key, $token_secret, $timestamp, $nonce, $time_diff); if (is_wp_error($signature)) { return $signature; } $auth = array('token' => $token_key, 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signature); $header_pieces = array(); foreach ($auth as $key => $value) { $header_pieces[] = sprintf('%s="%s"', $key, $value); } $authorization = 'X_JP_Auth ' . join(' ', $header_pieces); return $authorization; }
<?php global $current_user; $is_active = Jetpack::is_active(); $user_token = Jetpack_Data::get_access_token($current_user->ID); $is_user_connected = $user_token && !is_wp_error($user_token); $is_master_user = $current_user->ID == Jetpack_Options::get_option('master_user'); ?> </div><!-- .wrapper --> <div class="footer"> <nav class="primary nav-horizontal"> <div class="a8c-attribution"> <span> <?php echo sprintf(__('An %s Airline', 'jetpack'), '<a href="http://automattic.com/" class="a8c-logo">Automattic</a>'); ?> </span> </div> </nav><!-- .primary --> <nav class="secondary nav-horizontal"> <div class="secondary-footer"> <a href="http://jetpack.me">Jetpack <?php echo JETPACK__VERSION; ?> </a> <a href="http://wordpress.com/tos/"><?php esc_html_e('Terms', 'jetpack'); ?>
/** * Makes an authorized remote request using Jetpack_Signature * * @return array|WP_Error WP HTTP response on success */ public static function remote_request($args, $body = null) { $defaults = array('url' => '', 'user_id' => 0, 'blog_id' => 0, 'auth_location' => JETPACK_CLIENT__AUTH_LOCATION, 'method' => 'POST', 'timeout' => 10, 'redirection' => 0, 'headers' => array(), 'stream' => false, 'filename' => null); $args = wp_parse_args($args, $defaults); $args['blog_id'] = (int) $args['blog_id']; if ('header' != $args['auth_location']) { $args['auth_location'] = 'query_string'; } $token = Jetpack_Data::get_access_token($args['user_id']); if (!$token) { return new Jetpack_Error('missing_token'); } $method = strtoupper($args['method']); $timeout = intval($args['timeout']); $redirection = $args['redirection']; $stream = $args['stream']; $filename = $args['filename']; $request = compact('method', 'body', 'timeout', 'redirection', 'stream', 'filename'); @(list($token_key, $secret) = explode('.', $token->secret)); if (empty($token) || empty($secret)) { return new Jetpack_Error('malformed_token'); } $token_key = sprintf('%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id); require_once JETPACK__PLUGIN_DIR . 'class.jetpack-signature.php'; $time_diff = (int) Jetpack_Options::get_option('time_diff'); $jetpack_signature = new Jetpack_Signature($token->secret, $time_diff); $timestamp = time() + $time_diff; if (function_exists('wp_generate_password')) { $nonce = wp_generate_password(10, false); } else { $nonce = substr(sha1(rand(0, 1000000)), 0, 10); } // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing if (is_null($body)) { $body_hash = ''; } else { // Allow arrays to be used in passing data. $body_to_hash = $body; if (is_array($body)) { // We cast this to a new variable, because the array form of $body needs to be // maintained so it can be passed into the request later on in the code. if (count($body) > 0) { $body_to_hash = json_encode(self::_stringify_data($body)); } else { $body_to_hash = ''; } } if (!is_string($body_to_hash)) { return new Jetpack_Error('invalid_body', 'Body is malformed.'); } $body_hash = jetpack_sha1_base64($body_to_hash); } $auth = array('token' => $token_key, 'timestamp' => $timestamp, 'nonce' => $nonce, 'body-hash' => $body_hash); if (false !== strpos($args['url'], 'xmlrpc.php')) { $url_args = array('for' => 'jetpack', 'wpcom_blog_id' => Jetpack_Options::get_option('id')); } else { $url_args = array(); } if ('header' != $args['auth_location']) { $url_args += $auth; } $url = add_query_arg(urlencode_deep($url_args), $args['url']); $url = Jetpack::fix_url_for_bad_hosts($url); $signature = $jetpack_signature->sign_request($token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false); if (!$signature || is_wp_error($signature)) { return $signature; } // Send an Authorization header so various caches/proxies do the right thing $auth['signature'] = $signature; $auth['version'] = JETPACK__VERSION; $header_pieces = array(); foreach ($auth as $key => $value) { $header_pieces[] = sprintf('%s="%s"', $key, $value); } $request['headers'] = array_merge($args['headers'], array('Authorization' => "X_JETPACK " . join(' ', $header_pieces))); // Make sure we keep the host when we do JETPACK__WPCOM_JSON_API_HOST requests. $host = parse_url($url, PHP_URL_HOST); if ($host === JETPACK__WPCOM_JSON_API_HOST) { $request['headers']['Host'] = 'public-api.wordpress.com'; } if ('header' != $args['auth_location']) { $url = add_query_arg('signature', urlencode($signature), $url); } return Jetpack_Client::_wp_remote_request($url, $request); }