true; } /** * Attempts Jetpack registration. * * @param bool $tos_agree Whether the user agreed to TOS. * * @return bool|WP_Error */ public function try_registration( $tos_agree = true ) { if ( $tos_agree ) { $terms_of_service = new Terms_Of_Service(); $terms_of_service->agree(); } /** * Action fired when the user attempts the registration. * * @since 1.26.0 */ $pre_register = apply_filters( 'jetpack_pre_register', null ); if ( is_wp_error( $pre_register ) ) { return $pre_register; } $tracking_data = array(); if ( null !== $this->get_plugin() ) { $tracking_data['plugin_slug'] = $this->get_plugin()->get_slug(); } $tracking = new Tracking(); $tracking->record_user_event( 'jpc_register_begin', $tracking_data ); add_filter( 'jetpack_register_request_body', array( Utils::class, 'filter_register_request_body' ) ); $result = $this->register(); remove_filter( 'jetpack_register_request_body', array( Utils::class, 'filter_register_request_body' ) ); // If there was an error with registration and the site was not registered, record this so we can show a message. if ( ! $result || is_wp_error( $result ) ) { return $result; } return true; } /** * Adds a parameter to the register request body * * @since 1.26.0 * * @param string $name The name of the parameter to be added. * @param string $value The value of the parameter to be added. * * @throws \InvalidArgumentException If supplied arguments are not strings. * @return void */ public function add_register_request_param( $name, $value ) { if ( ! is_string( $name ) || ! is_string( $value ) ) { throw new \InvalidArgumentException( 'name and value must be strings' ); } self::$extra_register_params[ $name ] = $value; } /** * Takes the response from the Jetpack register new site endpoint and * verifies it worked properly. * * @since 1.7.0 * @since-jetpack 2.6.0 * * @param mixed $response the response object, or the error object. * @return string|WP_Error A JSON object on success or WP_Error on failures **/ protected function validate_remote_register_response( $response ) { if ( is_wp_error( $response ) ) { return new \WP_Error( 'register_http_request_failed', $response->get_error_message() ); } $code = wp_remote_retrieve_response_code( $response ); $entity = wp_remote_retrieve_body( $response ); if ( $entity ) { $registration_response = json_decode( $entity ); } else { $registration_response = false; } $code_type = (int) ( $code / 100 ); if ( 5 === $code_type ) { return new \WP_Error( 'wpcom_5??', $code ); } elseif ( 408 === $code ) { return new \WP_Error( 'wpcom_408', $code ); } 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-connection' ); } else { $error_description = isset( $registration_response->error_description ) ? (string) $registration_response->error_description : ''; } return new \WP_Error( (string) $registration_response->error, $error_description, $code ); } elseif ( 200 !== $code ) { return new \WP_Error( 'wpcom_bad_response', $code ); } // Jetpack ID error block. if ( empty( $registration_response->jetpack_id ) ) { return new \WP_Error( 'jetpack_id', /* translators: %s is an error message string */ sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack-connection' ), $entity ), $entity ); } elseif ( ! is_scalar( $registration_response->jetpack_id ) ) { return new \WP_Error( 'jetpack_id', /* translators: %s is an error message string */ sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack-connection' ), $entity ), $entity ); } elseif ( preg_match( '/[^0-9]/', $registration_response->jetpack_id ) ) { return new \WP_Error( 'jetpack_id', /* translators: %s is an error message string */ sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack-connection' ), $entity ), $entity ); } return $registration_response; } /** * Adds a used nonce to a list of known nonces. * * @param int $timestamp the current request timestamp. * @param string $nonce the nonce value. * @return bool whether the nonce is unique or not. * * @deprecated since 1.24.0 * @see Nonce_Handler::add() */ public function add_nonce( $timestamp, $nonce ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Nonce_Handler::add' ); return ( new Nonce_Handler() )->add( $timestamp, $nonce ); } /** * Cleans nonces that were saved when calling ::add_nonce. * * @todo Properly prepare the query before executing it. * * @param bool $all whether to clean even non-expired nonces. * * @deprecated since 1.24.0 * @see Nonce_Handler::clean_all() */ public function clean_nonces( $all = false ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Nonce_Handler::clean_all' ); ( new Nonce_Handler() )->clean_all( $all ? PHP_INT_MAX : ( time() - Nonce_Handler::LIFETIME ) ); } /** * Sets the Connection custom capabilities. * * @param string[] $caps Array of the user's capabilities. * @param string $cap Capability name. * @param int $user_id The user ID. * @param array $args Adds the context to the cap. Typically the object ID. */ public function jetpack_connection_custom_caps( $caps, $cap, $user_id, $args ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable switch ( $cap ) { case 'jetpack_connect': case 'jetpack_reconnect': $is_offline_mode = ( new Status() )->is_offline_mode(); if ( $is_offline_mode ) { $caps = array( 'do_not_allow' ); break; } // Pass through. If it's not offline mode, these should match disconnect. // Let users disconnect if it's offline mode, just in case things glitch. case 'jetpack_disconnect': /** * Filters the jetpack_disconnect capability. * * @since 1.14.2 * * @param array An array containing the capability name. */ $caps = apply_filters( 'jetpack_disconnect_cap', array( 'manage_options' ) ); break; case 'jetpack_connect_user': $is_offline_mode = ( new Status() )->is_offline_mode(); if ( $is_offline_mode ) { $caps = array( 'do_not_allow' ); break; } // With site connections in mind, non-admin users can connect their account only if a connection owner exists. $caps = $this->has_connected_owner() ? array( 'read' ) : array( 'manage_options' ); break; case 'jetpack_unlink_user': $is_offline_mode = ( new Status() )->is_offline_mode(); if ( $is_offline_mode ) { $caps = array( 'do_not_allow' ); break; } // Non-admins can always disconnect $caps = array( 'read' ); break; } return $caps; } /** * Builds the timeout limit for queries talking with the wpcom servers. * * Based on local php max_execution_time in php.ini * * @since 1.7.0 * @since-jetpack 5.4.0 * @return int **/ public function get_max_execution_time() { $timeout = (int) ini_get( 'max_execution_time' ); // Ensure exec time set in php.ini. if ( ! $timeout ) { $timeout = 30; } return $timeout; } /** * Sets a minimum request timeout, and returns the current timeout * * @since 1.7.0 * @since-jetpack 5.4.0 * @param int $min_timeout the minimum timeout value. **/ public function set_min_time_limit( $min_timeout ) { $timeout = $this->get_max_execution_time(); if ( $timeout < $min_timeout ) { $timeout = $min_timeout; set_time_limit( $timeout ); } return $timeout; } /** * Get our assumed site creation date. * Calculated based on the earlier date of either: * - Earliest admin user registration date. * - Earliest date of post of any post type. * * @since 1.7.0 * @since-jetpack 7.2.0 * * @return string Assumed site creation date and time. */ public function get_assumed_site_creation_date() { $cached_date = get_transient( 'jetpack_assumed_site_creation_date' ); if ( ! empty( $cached_date ) ) { return $cached_date; } /** * We don't use the 'ID' field, but need it to overcome a WP caching bug: https://core.trac.wordpress.org/ticket/62003 * * @todo Remote the 'ID' field from users fetching when the issue is fixed and Jetpack-supported WP versions move beyond it. */ $earliest_registered_users = get_users( array( 'role' => 'administrator', 'orderby' => 'user_registered', 'order' => 'ASC', 'fields' => array( 'ID', 'user_registered' ), 'number' => 1, ) ); $earliest_registration_date = $earliest_registered_users[0]->user_registered; $earliest_posts = get_posts( array( 'posts_per_page' => 1, 'post_type' => 'any', 'post_status' => 'any', 'orderby' => 'date', 'order' => 'ASC', ) ); // If there are no posts at all, we'll count only on user registration date. if ( $earliest_posts ) { $earliest_post_date = $earliest_posts[0]->post_date; } else { $earliest_post_date = PHP_INT_MAX; } $assumed_date = min( $earliest_registration_date, $earliest_post_date ); set_transient( 'jetpack_assumed_site_creation_date', $assumed_date ); return $assumed_date; } /** * Adds the activation source string as a parameter to passed arguments. * * @todo Refactor to use rawurlencode() instead of urlencode(). * * @param array $args arguments that need to have the source added. * @return array $amended arguments. */ public static function apply_activation_source_to_args( $args ) { list( $activation_source_name, $activation_source_keyword ) = get_option( 'jetpack_activation_source' ); if ( $activation_source_name ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.urlencode_urlencode $args['_as'] = urlencode( $activation_source_name ); } if ( $activation_source_keyword ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.urlencode_urlencode $args['_ak'] = urlencode( $activation_source_keyword ); } return $args; } /** * Generates two secret tokens and the end of life timestamp for them. * * @param string $action The action name. * @param int|bool $user_id The user identifier. * @param int $exp Expiration time in seconds. */ public function generate_secrets( $action, $user_id = false, $exp = 600 ) { return ( new Secrets() )->generate( $action, $user_id, $exp ); } /** * Returns two secret tokens and the end of life timestamp for them. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Secrets->get() instead. * * @param string $action The action name. * @param int $user_id The user identifier. * @return string|array an array of secrets or an error string. */ public function get_secrets( $action, $user_id ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Secrets->get' ); return ( new Secrets() )->get( $action, $user_id ); } /** * Deletes secret tokens in case they, for example, have expired. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Secrets->delete() instead. * * @param string $action The action name. * @param int $user_id The user identifier. */ public function delete_secrets( $action, $user_id ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Secrets->delete' ); ( new Secrets() )->delete( $action, $user_id ); } /** * Deletes all connection tokens and transients from the local Jetpack site. * If the plugin object has been provided in the constructor, the function first checks * whether it's the only active connection. * If there are any other connections, the function will do nothing and return `false` * (unless `$ignore_connected_plugins` is set to `true`). * * @param bool $ignore_connected_plugins Delete the tokens even if there are other connected plugins. * * @return bool True if disconnected successfully, false otherwise. */ public function delete_all_connection_tokens( $ignore_connected_plugins = false ) { // refuse to delete if we're not the last Jetpack plugin installed. if ( ! $ignore_connected_plugins && null !== $this->plugin && ! $this->plugin->is_only() ) { return false; } /** * Fires upon the disconnect attempt. * Return `false` to prevent the disconnect. * * @since 1.14.2 */ if ( ! apply_filters( 'jetpack_connection_delete_all_tokens', true ) ) { return false; } \Jetpack_Options::delete_option( array( 'master_user', 'time_diff', 'fallback_no_verify_ssl_certs', ) ); // Clear the memoized connection owner ID since it changed self::$connection_owner_id = null; ( new Secrets() )->delete_all(); $this->get_tokens()->delete_all(); // Delete cached connected user data. $transient_key = 'jetpack_connected_user_data_' . get_current_user_id(); delete_transient( $transient_key ); // Delete all XML-RPC errors. Error_Handler::get_instance()->delete_all_errors(); return true; } /** * Tells WordPress.com to disconnect the site and clear all tokens from cached site. * If the plugin object has been provided in the constructor, the function first check * whether it's the only active connection. * If there are any other connections, the function will do nothing and return `false` * (unless `$ignore_connected_plugins` is set to `true`). * * @param bool $ignore_connected_plugins Delete the tokens even if there are other connected plugins. * * @return bool True if disconnected successfully, false otherwise. */ public function disconnect_site_wpcom( $ignore_connected_plugins = false ) { if ( ! $ignore_connected_plugins && null !== $this->plugin && ! $this->plugin->is_only() ) { return false; } if ( ( new Status() )->is_offline_mode() && ! apply_filters( 'jetpack_connection_disconnect_site_wpcom_offline_mode', false ) ) { // Prevent potential disconnect of the live site by removing WPCOM tokens. return false; } /** * Fires upon the disconnect attempt. * Return `false` to prevent the disconnect. * * @since 1.14.2 */ if ( ! apply_filters( 'jetpack_connection_disconnect_site_wpcom', true, $this ) ) { return false; } $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.deregister', get_current_user_id() ); return true; } /** * Disconnect the plugin and remove the tokens. * This function will automatically perform "soft" or "hard" disconnect depending on whether other plugins are using the connection. * This is a proxy method to simplify the Connection package API. * * @see Manager::disconnect_site() * * @param boolean $disconnect_wpcom Should disconnect_site_wpcom be called. * @param bool $ignore_connected_plugins Delete the tokens even if there are other connected plugins. * @return bool */ public function remove_connection( $disconnect_wpcom = true, $ignore_connected_plugins = false ) { $this->disconnect_site( $disconnect_wpcom, $ignore_connected_plugins ); return true; } /** * Completely clearing up the connection, and initiating reconnect. * * @return true|WP_Error True if reconnected successfully, a `WP_Error` object otherwise. */ public function reconnect() { ( new Tracking() )->record_user_event( 'restore_connection_reconnect' ); $this->disconnect_site_wpcom( true ); return $this->register(); } /** * Validate the tokens, and refresh the invalid ones. * * @return string|bool|WP_Error True if connection restored or string indicating what's to be done next. A `WP_Error` object or false otherwise. */ public function restore() { // If this is a site connection we need to trigger a full reconnection as our only secure means of // communication with WPCOM, aka the blog token, is compromised. if ( $this->is_site_connection() ) { return $this->reconnect(); } $validate_tokens_response = $this->get_tokens()->validate(); // If token validation failed, trigger a full reconnection. if ( is_array( $validate_tokens_response ) && isset( $validate_tokens_response['blog_token']['is_healthy'] ) && isset( $validate_tokens_response['user_token']['is_healthy'] ) ) { $blog_token_healthy = $validate_tokens_response['blog_token']['is_healthy']; $user_token_healthy = $validate_tokens_response['user_token']['is_healthy']; } else { $blog_token_healthy = false; $user_token_healthy = false; } // Tokens are both valid, or both invalid. We can't fix the problem we don't see, so the full reconnection is needed. if ( $blog_token_healthy === $user_token_healthy ) { $result = $this->reconnect(); return ( true === $result ) ? 'authorize' : $result; } if ( ! $blog_token_healthy ) { return $this->refresh_blog_token(); } if ( ! $user_token_healthy ) { return ( true === $this->refresh_user_token() ) ? 'authorize' : false; } return false; } /** * Responds to a WordPress.com call to register the current site. * Should be changed to protected. * * @param array $registration_data Array of [ secret_1, user_id ]. */ public function handle_registration( array $registration_data ) { list( $registration_secret_1, $registration_user_id ) = $registration_data; if ( empty( $registration_user_id ) ) { return new \WP_Error( 'registration_state_invalid', __( 'Invalid Registration State', 'jetpack-connection' ), 400 ); } return ( new Secrets() )->verify( 'register', $registration_secret_1, (int) $registration_user_id ); } /** * Perform the API request to validate the blog and user tokens. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Tokens->validate_tokens() instead. * * @param int|null $user_id ID of the user we need to validate token for. Current user's ID by default. * * @return array|false|WP_Error The API response: `array( 'blog_token_is_healthy' => true|false, 'user_token_is_healthy' => true|false )`. */ public function validate_tokens( $user_id = null ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Tokens->validate' ); return $this->get_tokens()->validate( $user_id ); } /** * Verify a Previously Generated Secret. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Secrets->verify() instead. * * @param string $action The type of secret to verify. * @param string $secret_1 The secret string to compare to what is stored. * @param int $user_id The user ID of the owner of the secret. * @return \WP_Error|string WP_Error on failure, secret_2 on success. */ public function verify_secrets( $action, $secret_1, $user_id ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Secrets->verify' ); return ( new Secrets() )->verify( $action, $secret_1, $user_id ); } /** * Responds to a WordPress.com call to authorize the current user. * Should be changed to protected. */ public function handle_authorization() { } /** * Obtains the auth token. * * @param array $data The request data. * @return object|\WP_Error Returns the auth token on success. * Returns a \WP_Error on failure. */ public function get_token( $data ) { return $this->get_tokens()->get( $data, $this->api_url( 'token' ) ); } /** * Builds a URL to the Jetpack connection auth page. * * @since 2.7.6 Added optional $from and $raw parameters. * * @param WP_User|null $user (optional) defaults to the current logged in user. * @param string|null $redirect (optional) a redirect URL to use instead of the default. * @param bool|string $from If not false, adds 'from=$from' param to the connect URL. * @param bool $raw If true, URL will not be escaped. * * @return string Connect URL. */ public function get_authorization_url( $user = null, $redirect = null, $from = false, $raw = false ) { if ( empty( $user ) ) { $user = wp_get_current_user(); } $roles = new Roles(); $role = $roles->translate_user_to_role( $user ); $signed_role = $this->get_tokens()->sign_role( $role ); /** * Filter the URL of the first time the user gets redirected back to your site for connection * data processing. * * @since 1.7.0 * @since-jetpack 8.0.0 * * @param string $redirect_url Defaults to the site admin URL. */ $processing_url = apply_filters( 'jetpack_connect_processing_url', admin_url( 'admin.php' ) ); /** * Filter the URL to redirect the user back to when the authorization process * is complete. * * @since 1.7.0 * @since-jetpack 8.0.0 * * @param string $redirect_url Defaults to the site URL. */ $redirect = apply_filters( 'jetpack_connect_redirect_url', $redirect ); $secrets = ( new Secrets() )->generate( 'authorize', $user->ID, 2 * HOUR_IN_SECONDS ); /** * Filter the type of authorization. * 'calypso' completes authorization on wordpress.com/jetpack/connect * while 'jetpack' ( or any other value ) completes the authorization at jetpack.wordpress.com. * * @since 1.7.0 * @since-jetpack 4.3.3 * * @param string $auth_type Defaults to 'calypso', can also be 'jetpack'. */ $auth_type = apply_filters( 'jetpack_auth_type', 'calypso' ); /** * Filters the user connection request data for additional property addition. * * @since 1.7.0 * @since-jetpack 8.0.0 * * @param array $request_data request data. */ $body = apply_filters( 'jetpack_connect_request_body', array( 'response_type' => 'code', 'client_id' => \Jetpack_Options::get_option( 'id' ), 'redirect_uri' => add_query_arg( array( 'handler' => 'jetpack-connection-webhooks', 'action' => 'authorize', '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ), 'redirect' => $redirect ? rawurlencode( $redirect ) : false, ), esc_url( $processing_url ) ), 'state' => $user->ID, 'scope' => $signed_role, 'user_email' => $user->user_email, 'user_login' => $user->user_login, 'is_active' => $this->has_connected_owner(), // TODO Deprecate this. 'jp_version' => (string) Constants::get_constant( 'JETPACK__VERSION' ), 'auth_type' => $auth_type, 'secret' => $secrets['secret_1'], 'blogname' => get_option( 'blogname' ), 'site_url' => Urls::site_url(), 'home_url' => Urls::home_url(), 'site_icon' => get_site_icon_url(), 'site_lang' => get_locale(), 'site_created' => $this->get_assumed_site_creation_date(), 'allow_site_connection' => ! $this->has_connected_owner(), 'calypso_env' => ( new Host() )->get_calypso_env(), 'source' => ( new Host() )->get_source_query(), ) ); $body = static::apply_activation_source_to_args( urlencode_deep( $body ) ); $api_url = $this->api_url( 'authorize' ); $url = add_query_arg( $body, $api_url ); if ( is_network_admin() ) { $url = add_query_arg( 'is_multisite', network_admin_url( 'admin.php?page=jetpack-settings' ), $url ); } if ( $from ) { $url = add_query_arg( 'from', $from, $url ); } if ( $raw ) { $url = esc_url_raw( $url ); } /** * Filter the URL used when connecting a user to a WordPress.com account. * * @since 2.0.0 * @since 2.7.6 Added $raw parameter. * * @param string $url Connection URL. * @param bool $raw If true, URL will not be escaped. */ return apply_filters( 'jetpack_build_authorize_url', $url, $raw ); } /** * Authorizes the user by obtaining and storing the user token. * * @param array $data The request data. * @return string|\WP_Error Returns a string on success. * Returns a \WP_Error on failure. */ public function authorize( $data = array() ) { /** * Action fired when user authorization starts. * * @since 1.7.0 * @since-jetpack 8.0.0 */ do_action( 'jetpack_authorize_starting' ); $roles = new Roles(); $role = $roles->translate_current_user_to_role(); if ( ! $role ) { return new \WP_Error( 'no_role', 'Invalid request.', 400 ); } $cap = $roles->translate_role_to_cap( $role ); if ( ! $cap ) { return new \WP_Error( 'no_cap', 'Invalid request.', 400 ); } if ( ! empty( $data['error'] ) ) { return new \WP_Error( $data['error'], 'Error included in the request.', 400 ); } if ( ! isset( $data['state'] ) ) { return new \WP_Error( 'no_state', 'Request must include state.', 400 ); } if ( ! ctype_digit( $data['state'] ) ) { return new \WP_Error( $data['error'], 'State must be an integer.', 400 ); } $current_user_id = get_current_user_id(); if ( $current_user_id !== (int) $data['state'] ) { return new \WP_Error( 'wrong_state', 'State does not match current user.', 400 ); } if ( empty( $data['code'] ) ) { return new \WP_Error( 'no_code', 'Request must include an authorization code.', 400 ); } $token = $this->get_tokens()->get( $data, $this->api_url( 'token' ) ); if ( is_wp_error( $token ) ) { $code = $token->get_error_code(); if ( empty( $code ) ) { $code = 'invalid_token'; } return new \WP_Error( $code, $token->get_error_message(), 400 ); } if ( ! $token ) { return new \WP_Error( 'no_token', 'Error generating token.', 400 ); } $is_connection_owner = ! $this->has_connected_owner(); $this->get_tokens()->update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_connection_owner ); /** * Fires after user has successfully received an auth token. * * @since 1.7.0 * @since-jetpack 3.9.0 */ do_action( 'jetpack_user_authorized' ); if ( ! $is_connection_owner ) { /** * Action fired when a secondary user has been authorized. * * @since 1.7.0 * @since-jetpack 8.0.0 */ do_action( 'jetpack_authorize_ending_linked' ); return 'linked'; } /** * Action fired when the master user has been authorized. * * @since 1.7.0 * @since-jetpack 8.0.0 * * @param array $data The request data. */ do_action( 'jetpack_authorize_ending_authorized', $data ); \Jetpack_Options::delete_raw_option( 'jetpack_last_connect_url_check' ); ( new Nonce_Handler() )->reschedule(); return 'authorized'; } /** * Disconnects from the Jetpack servers. * Forgets all connection details and tells the Jetpack servers to do the same. * * @param boolean $disconnect_wpcom Should disconnect_site_wpcom be called. * @param bool $ignore_connected_plugins Delete the tokens even if there are other connected plugins. */ public function disconnect_site( $disconnect_wpcom = true, $ignore_connected_plugins = true ) { if ( ! $ignore_connected_plugins && null !== $this->plugin && ! $this->plugin->is_only() ) { return false; } wp_clear_scheduled_hook( 'jetpack_clean_nonces' ); ( new Nonce_Handler() )->clean_all(); Heartbeat::init()->deactivate(); /** * Fires before a site is disconnected. * * @since 1.36.3 */ do_action( 'jetpack_site_before_disconnected' ); // If the site is in an IDC because sync is not allowed, // let's make sure to not disconnect the production site. if ( $disconnect_wpcom ) { $tracking = new Tracking(); $tracking->record_user_event( 'disconnect_site', array() ); $this->disconnect_site_wpcom( $ignore_connected_plugins ); } $this->delete_all_connection_tokens( $ignore_connected_plugins ); // Remove tracked package versions, since they depend on the Jetpack Connection. delete_option( Package_Version_Tracker::PACKAGE_VERSION_OPTION ); $jetpack_unique_connection = \Jetpack_Options::get_option( 'unique_connection' ); if ( $jetpack_unique_connection ) { // Check then record unique disconnection if site has never been disconnected previously. if ( - 1 === $jetpack_unique_connection['disconnected'] ) { $jetpack_unique_connection['disconnected'] = 1; } else { if ( 0 === $jetpack_unique_connection['disconnected'] ) { $a8c_mc_stats_instance = new A8c_Mc_Stats(); $a8c_mc_stats_instance->add( 'connections', 'unique-disconnect' ); $a8c_mc_stats_instance->do_server_side_stats(); } // increment number of times disconnected. $jetpack_unique_connection['disconnected'] += 1; } \Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection ); } /** * Fires when a site is disconnected. * * @since 1.30.1 */ do_action( 'jetpack_site_disconnected' ); } /** * The Base64 Encoding of the SHA1 Hash of the Input. * * @param string $text The string to hash. * @return string */ public function sha1_base64( $text ) { return base64_encode( sha1( $text, true ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode } /** * This function mirrors Jetpack_Data::is_usable_domain() in the WPCOM codebase. * * @param string $domain The domain to check. * * @return bool|WP_Error */ public function is_usable_domain( $domain ) { // If it's empty, just fail out. if ( ! $domain ) { return new \WP_Error( 'fail_domain_empty', /* translators: %1$s is a domain name. */ sprintf( __( 'Domain `%1$s` just failed is_usable_domain check as it is empty.', 'jetpack-connection' ), $domain ) ); } /** * Skips the usuable domain check when connecting a site. * * Allows site administrators with domains that fail gethostname-based checks to pass the request to WP.com * * @since 1.7.0 * @since-jetpack 4.1.0 * * @param bool If the check should be skipped. Default false. */ if ( apply_filters( 'jetpack_skip_usuable_domain_check', false ) ) { return true; } // None of the explicit localhosts. $forbidden_domains = array( 'wordpress.com', 'localhost', 'localhost.localdomain', 'local.wordpress.test', // VVV pattern. 'local.wordpress-trunk.test', // VVV pattern. 'src.wordpress-develop.test', // VVV pattern. 'build.wordpress-develop.test', // VVV pattern. ); if ( in_array( $domain, $forbidden_domains, true ) ) { return new \WP_Error( 'fail_domain_forbidden', sprintf( /* translators: %1$s is a domain name. */ __( 'Domain `%1$s` just failed is_usable_domain check as it is in the forbidden array.', 'jetpack-connection' ), $domain ) ); } // No .test or .local domains. if ( preg_match( '#\.(test|local)$#i', $domain ) ) { return new \WP_Error( 'fail_domain_tld', sprintf( /* translators: %1$s is a domain name. */ __( 'Domain `%1$s` just failed is_usable_domain check as it uses an invalid top level domain.', 'jetpack-connection' ), $domain ) ); } // No WPCOM subdomains. if ( preg_match( '#\.WordPress\.com$#i', $domain ) ) { return new \WP_Error( 'fail_subdomain_wpcom', sprintf( /* translators: %1$s is a domain name. */ __( 'Domain `%1$s` just failed is_usable_domain check as it is a subdomain of WordPress.com.', 'jetpack-connection' ), $domain ) ); } // If PHP was compiled without support for the Filter module (very edge case). if ( ! function_exists( 'filter_var' ) ) { // Just pass back true for now, and let wpcom sort it out. return true; } $domain = preg_replace( '#^https?://#', '', untrailingslashit( $domain ) ); if ( filter_var( $domain, FILTER_VALIDATE_IP ) && ! filter_var( $domain, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) { return new \WP_Error( 'fail_ip_forbidden', sprintf( /* translators: %1$s is a domain name. */ __( 'IP address `%1$s` just failed is_usable_domain check as it is in the private network.', 'jetpack-connection' ), $domain ) ); } return true; } /** * Gets the requested token. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Tokens->get_access_token() instead. * * @param int|false $user_id false: Return the Blog Token. int: Return that user's User Token. * @param string|false $token_key If provided, check that the token matches the provided input. * @param bool|true $suppress_errors If true, return a falsy value when the token isn't found; When false, return a descriptive WP_Error when the token isn't found. * * @return object|false * * @see $this->get_tokens()->get_access_token() */ public function get_access_token( $user_id = false, $token_key = false, $suppress_errors = true ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Tokens->get_access_token' ); return $this->get_tokens()->get_access_token( $user_id, $token_key, $suppress_errors ); } /** * In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths * since it is passed by reference to various methods. * Capture it here so we can verify the signature later. * * @param array $methods an array of available XMLRPC methods. * @return array the same array, since this method doesn't add or remove anything. */ public function xmlrpc_methods( $methods ) { $this->raw_post_data = isset( $GLOBALS['HTTP_RAW_POST_DATA'] ) ? $GLOBALS['HTTP_RAW_POST_DATA'] : null; return $methods; } /** * Resets the raw post data parameter for testing purposes. */ public function reset_raw_post_data() { $this->raw_post_data = null; } /** * Registering an additional method. * * @param array $methods an array of available XMLRPC methods. * @return array the amended array in case the method is added. */ public function public_xmlrpc_methods( $methods ) { if ( array_key_exists( 'wp.getOptions', $methods ) ) { $methods['wp.getOptions'] = array( $this, 'jetpack_get_options' ); } return $methods; } /** * Handles a getOptions XMLRPC method call. * * @param array $args method call arguments. * @return array|IXR_Error An amended XMLRPC server options array. */ public function jetpack_get_options( $args ) { global $wp_xmlrpc_server; $wp_xmlrpc_server->escape( $args ); $username = $args[1]; $password = $args[2]; $user = $wp_xmlrpc_server->login( $username, $password ); if ( ! $user ) { return $wp_xmlrpc_server->error; } $options = array(); $user_data = $this->get_connected_user_data(); if ( is_array( $user_data ) ) { $options['jetpack_user_id'] = array( 'desc' => __( 'The WP.com user ID of the connected user', 'jetpack-connection' ), 'readonly' => true, 'value' => $user_data['ID'], ); $options['jetpack_user_login'] = array( 'desc' => __( 'The WP.com username of the connected user', 'jetpack-connection' ), 'readonly' => true, 'value' => $user_data['login'], ); $options['jetpack_user_email'] = array( 'desc' => __( 'The WP.com user email of the connected user', 'jetpack-connection' ), 'readonly' => true, 'value' => $user_data['email'], ); $options['jetpack_user_site_count'] = array( 'desc' => __( 'The number of sites of the connected WP.com user', 'jetpack-connection' ), 'readonly' => true, 'value' => $user_data['site_count'], ); } $wp_xmlrpc_server->blog_options = array_merge( $wp_xmlrpc_server->blog_options, $options ); $args = stripslashes_deep( $args ); return $wp_xmlrpc_server->wp_getOptions( $args ); } /** * Adds Jetpack-specific options to the output of the XMLRPC options method. * * @param array $options standard Core options. * @return array amended options. */ public function xmlrpc_options( $options ) { $jetpack_client_id = false; if ( $this->is_connected() ) { $jetpack_client_id = \Jetpack_Options::get_option( 'id' ); } $options['jetpack_version'] = array( 'desc' => __( 'Jetpack Plugin Version', 'jetpack-connection' ), 'readonly' => true, 'value' => Constants::get_constant( 'JETPACK__VERSION' ), ); $options['jetpack_client_id'] = array( 'desc' => __( 'The Client ID/WP.com Blog ID of this site', 'jetpack-connection' ), 'readonly' => true, 'value' => $jetpack_client_id, ); return $options; } /** * Resets the saved authentication state in between testing requests. */ public function reset_saved_auth_state() { $this->xmlrpc_verification = null; } /** * Sign a user role with the master access token. * If not specified, will default to the current user. * * @access public * * @param string $role User role. * @param int $user_id ID of the user. * @return string Signed user role. */ public function sign_role( $role, $user_id = null ) { return $this->get_tokens()->sign_role( $role, $user_id ); } /** * Set the plugin instance. * * @param Plugin $plugin_instance The plugin instance. * * @return $this */ public function set_plugin_instance( Plugin $plugin_instance ) { $this->plugin = $plugin_instance; return $this; } /** * Retrieve the plugin management object. * * @return Plugin|null */ public function get_plugin() { return $this->plugin; } /** * Get all connected plugins information, excluding those disconnected by user. * WARNING: the method cannot be called until Plugin_Storage::configure is called, which happens on plugins_loaded * Even if you don't use Jetpack Config, it may be introduced later by other plugins, * so please make sure not to run the method too early in the code. * * @return array|WP_Error */ public function get_connected_plugins() { $maybe_plugins = Plugin_Storage::get_all(); if ( $maybe_plugins instanceof WP_Error ) { return $maybe_plugins; } return $maybe_plugins; } /** * Force plugin disconnect. After its called, the plugin will not be allowed to use the connection. * Note: this method does not remove any access tokens. * * @deprecated since 1.39.0 * @return bool */ public function disable_plugin() { return null; } /** * Force plugin reconnect after user-initiated disconnect. * After its called, the plugin will be allowed to use the connection again. * Note: this method does not initialize access tokens. * * @deprecated since 1.39.0. * @return bool */ public function enable_plugin() { return null; } /** * Whether the plugin is allowed to use the connection, or it's been disconnected by user. * If no plugin slug was passed into the constructor, always returns true. * * @deprecated 1.42.0 This method no longer has a purpose after the removal of the soft disconnect feature. * * @return bool */ public function is_plugin_enabled() { return true; } /** * Perform the API request to refresh the blog token. * Note that we are making this request on behalf of the Jetpack master user, * given they were (most probably) the ones that registered the site at the first place. * * @return WP_Error|bool The result of updating the blog_token option. */ public function refresh_blog_token() { ( new Tracking() )->record_user_event( 'restore_connection_refresh_blog_token' ); $blog_id = \Jetpack_Options::get_option( 'id' ); if ( ! $blog_id ) { return new WP_Error( 'site_not_registered', 'Site not registered.' ); } $url = sprintf( '%s/%s/v%s/%s', Constants::get_constant( 'JETPACK__WPCOM_JSON_API_BASE' ), 'wpcom', '2', 'sites/' . $blog_id . '/jetpack-refresh-blog-token' ); $method = 'POST'; $user_id = get_current_user_id(); $response = Client::remote_request( compact( 'url', 'method', 'user_id' ) ); if ( is_wp_error( $response ) ) { return new WP_Error( 'refresh_blog_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 ) { if ( empty( $json->code ) ) { return new WP_Error( 'unknown', '', $code ); } /* translators: Error description string. */ $error_description = isset( $json->message ) ? sprintf( __( 'Error Details: %s', 'jetpack-connection' ), (string) $json->message ) : ''; return new WP_Error( (string) $json->code, $error_description, $code ); } if ( empty( $json->jetpack_secret ) || ! is_scalar( $json->jetpack_secret ) ) { return new WP_Error( 'jetpack_secret', '', $code ); } Error_Handler::get_instance()->delete_all_errors(); return $this->get_tokens()->update_blog_token( (string) $json->jetpack_secret ); } /** * Disconnect the user from WP.com, and initiate the reconnect process. * * @return bool */ public function refresh_user_token() { ( new Tracking() )->record_user_event( 'restore_connection_refresh_user_token' ); $this->disconnect_user( null, true, true ); return true; } /** * Fetches a signed token. * * @deprecated 1.24.0 Use Automattic\Jetpack\Connection\Tokens->get_signed_token() instead. * * @param object $token the token. * @return WP_Error|string a signed token */ public function get_signed_token( $token ) { _deprecated_function( __METHOD__, '1.24.0', 'Automattic\\Jetpack\\Connection\\Tokens->get_signed_token' ); return $this->get_tokens()->get_signed_token( $token ); } /** * If the site-level connection is active, add the list of plugins using connection to the heartbeat (except Jetpack itself) * * @since 6.11.0 Add the list of Jetpack package versions to the heartbeat. * * @param array $stats The Heartbeat stats array. * @return array $stats */ public function add_stats_to_heartbeat( $stats ) { if ( ! $this->is_connected() ) { return $stats; } $active_plugins_using_connection = Plugin_Storage::get_all(); foreach ( array_keys( $active_plugins_using_connection ) as $plugin_slug ) { if ( 'jetpack' !== $plugin_slug ) { $stats_group = isset( $active_plugins_using_connection['jetpack'] ) ? 'combined-connection' : 'standalone-connection'; $stats[ $stats_group ][] = $plugin_slug; } } $stats['jetpack_package_versions'] = apply_filters( 'jetpack_package_versions', array() ); return $stats; } /** * Get the WPCOM or self-hosted site ID. * * @param bool $quiet Return null instead of an error. * * @return int|WP_Error|null */ public static function get_site_id( $quiet = false ) { $is_wpcom = ( defined( 'IS_WPCOM' ) && IS_WPCOM ); $site_id = $is_wpcom ? get_current_blog_id() : \Jetpack_Options::get_option( 'id' ); if ( ! $site_id ) { return $quiet ? null : new \WP_Error( 'unavailable_site_id', __( 'Sorry, something is wrong with your Jetpack connection.', 'jetpack-connection' ), 403 ); } return (int) $site_id; } /** * Check if Jetpack is ready for uninstall cleanup. * * @param string $current_plugin_slug The current plugin's slug. * * @return bool */ public static function is_ready_for_cleanup( $current_plugin_slug ) { $active_plugins = get_option( Plugin_Storage::ACTIVE_PLUGINS_OPTION_NAME ); return empty( $active_plugins ) || ! is_array( $active_plugins ) || ( count( $active_plugins ) === 1 && array_key_exists( $current_plugin_slug, $active_plugins ) ); } } Ipad Air 2 charging flix – alibabatelecom
ADD ANYTHING HERE OR JUST REMOVE IT…
  • NEWSLETTER
  • CONTACT US
  • FAQs
alibabatelecom
Select category
  • Select category
  • Accessories
    • Mouse , Keyboard
    • phone card holder
    • Phone holder
    • Pop socket
    • Selfi
    • USB-SD Memory card
  • brands
    • ACEFAST
    • AMA Book Case
    • AMA Extra pas Book Case
    • Anti shock
      • Iphone
    • Apple
    • Back case card holder
    • back case color
      • Luxury clear magnetic back case
    • BOROFONE
    • Fashion Case
    • Hoco
    • ideal of Sweden
    • KEY Book Case
    • kingston Memory
    • Magnet leather case
    • OG Tempered Glass
    • Samsung
  • Childeren toys
    • Car , Motor
  • Electronics
    • Adapters
    • Air Tag
    • Bluetooth Speaker
    • Cables
    • Car adapter , cables
    • Gaming
    • HDMI , converter
    • Headset , audio jack
    • Oudio Other
    • Wirless charger
  • Mobile , Ipad , watch cases
    • Ipad case
  • Mobile , Tab , Watch parts
    • Ipad
      • Ipad battery
      • Ipad charging port
      • Ipad display
    • Iphone
      • Iphone back camera
      • Iphone Back cover
      • Iphone battery
      • Iphone camera lens
      • Iphone charging port
      • Iphone display
      • Iphone earspeaker
      • Iphone front camera
      • Iphone loudspeaker
      • iphone parts
      • Iphone Simcard holder
    • Samsung
      • Main Flex
      • Power And Volume Flex Cable
      • Samsung back camera
      • Samsung back cover
      • Samsung battery
      • Samsung camera lens
      • Samsung charging port
      • Samsung display
      • Samsung earspeaker
      • Samsung front camera
      • Samsung LCD Flex
      • Samsung loudspeaker
      • Samsung Signal Antenna
      • Samsung Simcard holder
  • Mobile , Tablets Accessories
    • Apple
      • Apple Watch
        • Apple watch 3 serie 40mm
        • Apple watch 3 serie 42mm
        • Apple watch 4 serie 38mm
        • Apple watch 4 serie 42mm
        • Apple watch 5 serie 40mm
        • Apple watch 5 serie 44mm
        • Apple watch 6 serie 40mm
        • Apple watch 6 serie 44mm
        • Apple watch 7 serie 41mm
        • Apple watch 7 serie 45mm
        • Apple watch 8 serie 41mm
        • Apple watch 8 serie 45mm
        • Apple watch Ultra 49mm 1st Gen
      • IPad
        • iPad 10.2 7th Ge (2019)
        • iPad 10.2 8th Ge (2020)
        • iPad 10.2 9th Ge (2021)
        • iPad 10.9 (10th 2022)
        • iPad 11 (11Gen 2025 )
        • Ipad 3
        • Ipad 4
        • iPad 9.7 (5th 2017)
        • iPad 9.7 (6th 2018)
        • iPad Air (2013)
        • iPad Air 11 (2024)
        • iPad Air 11 (2025)
        • iPad Air 13 (2024)
        • iPad Air 13 (2025)
        • Ipad Air 2 (2014)
        • iPad Air 3rd Ge (2019)
        • iPad Air 4th Ge (2020)
        • iPad Air 5th Ge (2022)
        • ipad mini 4th Ge (2015)
        • ipad mini 5th Ge (2019)
        • ipad mini 6th Ge (2021)
        • iPad Pro 10.5 (2017)
        • iPad Pro 11 (1Gen 2018)
        • iPad Pro 11 (2 Gen: 2020)
        • iPad Pro 11 (3Gen 2021)
        • iPad Pro 11 (4 Gen: 2022)
        • iPad Pro 11 (5 Gen: 2024) M4
        • iPad Pro 12.9 (1nd 2015)
        • iPad Pro 12.9 (2nd 2017)
        • iPad Pro 12.9 (3nd 2018)
        • iPad Pro 12.9 (4nd 2020)
        • iPad Pro 12.9 (5nd 2021)
        • iPad Pro 12.9 (6nd 2022)
        • IPad Pro 13 (2024)(13-inch (M4)
        • iPad Pro 13 (2025)(13-inch (M5)
        • iPad Pro 9.7 (2016)
      • Iphone
        • iphone 11
        • iphone 11 pro
        • iphone 11 pro max
        • iphone 12
        • iphone 12 mini
        • iphone 12 pro
        • iphone 12 pro max
        • iphone 13
        • iphone 13 mini
        • iphone 13 pro
        • iphone 13 pro max
        • iphone 14
        • iphone 14 plus
        • iphone 14 pro
        • iphone 14 pro max
        • Iphone 15
        • Iphone 15 Plus
        • Iphone 15 Pro
        • Iphone 15 Pro Max
        • Iphone 16
        • Iphone 16 Plus
        • Iphone 16 Pro
        • Iphone 16 Pro Max
        • Iphone 16e
        • Iphone 17
        • Iphone 17 Air
        • Iphone 17 Pro
        • Iphone 17 Pro Max
        • Iphone 17e
        • iphone 5
        • iphone 5S
        • Iphone 6
        • iphone 6 plus
        • iphone 6s
        • iphone 6s plus
        • iphone 7
        • iphone 7 plus
        • iphone 8
        • iphone 8 plus
        • iphone SE
        • iphone SE 2020
        • Iphone SE 2022
        • iphone X
        • iphone XR
        • iphone XS
        • iphone XS max
    • google
      • Google Pixel 5
      • Google Pixel 5A
      • Google Pixel 6
      • Google Pixel 6 Pro
      • Google Pixel 6A
      • Google Pixel 7
      • Google Pixel 7 Pro
      • Google Pixel 7A
      • Google Pixel 8
      • Google Pixel 8 Pro
      • Google Pixel 8A
      • Google Pixel 9
      • Google Pixel 9 Pro
      • Google Pixel 9 Pro XL
    • Huawei
      • Huawei Honor Models
        • Huawei Honor 10
        • Huawei Honor 20
        • Huawei Honor 20 Lite
        • Huawei Honor 20 Pro
        • Huawei Honor 6
        • Huawei Honor 7
        • Huawei Honor 8
        • Huawei Honor 8 Lite
        • Huawei Honor 9
        • Huawei Honor View 10
        • Huawei Honor View 20
      • Huawei Mate Models
        • Huawei Mate 10
        • Huawei Mate 10 Lite
        • Huawei Mate 10 Pro
        • Huawei Mate 20
        • Huawei Mate 20 Lite
        • Huawei Mate 20 Pro
        • Huawei Mate 30
        • Huawei Mate 30 Lite
        • Huawei Mate 30 Pro
        • Huawei Mate 40
        • Huawei Mate 40 Pro
        • Huawei Mate 7
        • Huawei Mate 8
        • Huawei Mate 9
        • Huawei Mate 9 pro
      • Huawei P Models
        • Huawei P10
        • Huawei P10 Lite
        • Huawei P20
        • Huawei P20 Lite
        • Huawei P20 Lite 2019
        • Huawei P20 Pro
        • Huawei P30
        • Huawei P30 Lite
        • Huawei P30 Pro
        • Huawei P40
        • Huawei P40 Lite
        • Huawei P40 pro
        • Huawei P7
        • Huawei P8
        • Huawei P8 Lite
        • Huawei P9
        • Huawei P9 Lite
      • Huawei P smart Models
        • Huawei P smart
        • Huawei P smart 2019
        • Huawei P smart 2020
        • Huawei P smart 2021
        • Huawei P smart pro
        • Huawei P smart Z
    • Nokia
      • HMD Series
        • Nokia 2.4
        • Nokia 5.4
    • Samsung
      • Samsung A model
        • |Samsung A34 (A346)
        • Samsung A 57
        • Samsung A01
        • Samsung A02
        • samsung A02s
        • Samsung A03
        • Samsung A03s
        • Samsung A04s
        • Samsung A05S
        • Samsung A06
        • Samsung A07
        • Samsung A10
        • Samsung A10s
        • Samsung A11
        • Samsung A12
        • Samsung A13 4G
        • Samsung A13 5G
        • Samsung A14 4G
        • Samsung A14 5G
        • Samsung A15
        • Samsung A16 4G (A165F)
        • Samsung A16 5G (A166B)
        • Samsung A17
        • Samsung A20 (205F)
        • Samsung A20e (A202F)
        • Samsung A20s (A207F)
        • Samsung A21 (A215)
        • Samsung A21s (A217F)
        • Samsung A22 4G (A225F)
        • Samsung A22 5G (A226B)
        • Samsung A23 4G (SM-A236)
        • Samsung A23 5G (SM-A236)
        • Samsung A24 (A245F)
        • Samsung A25 (A256)
        • Samsung A26 (A266)
        • Samsung A27
        • Samsung A30 (A305F)
        • Samsung A30s (A307F)
        • Samsung A31 (A315F)
        • Samsung A32 4G (A325)
        • Samsung A32 5G (A326)
        • Samsung A33 5G (A336B)
        • Samsung A35 (A356)
        • Samsung A36 (A366)
        • Samsung A37
        • Samsung A40 (A405F)
        • Samsung A41 (A415F)
        • Samsung A42 (A426B)
        • Samsung A5 2015
        • Samsung A50 (A505F)
        • Samsung A50s
        • Samsung A51 (A515F)
        • Samsung A51 5G (A516B/DS)
        • Samsung A52 (A525F)
        • Samsung A52s (A528B)
        • Samsung A53 (A536B/DS)
        • Samsung A54 (A546B)
        • Samsung A55 (A556)
        • Samsung A56 (A566)
        • Samsung A60 (A606F)
        • Samsung A70 (A705F)
        • Samsung A71 5G (A716F)
        • Samsung A72 (A725)
        • Samsung A73
        • Samsung A80 (A805F)
        • Samsung A90 (A908F)
      • Samsung Buds case
      • Samsung note model
        • Samsung Note 10
        • Samsung Note 10 Lite
        • Samsung Note 10 plus
        • Samsung Note 20
        • Samsung Note 20 ultra
        • Samsung Note 8
        • Samsung Note 9
      • Samsung S model
        • Samsung s10
        • Samsung S10 lite
        • Samsung s10 plus
        • Samsung s10e
        • Samsung s20
        • Samsung s20 FE
        • Samsung s20 plus
        • Samsung s20 ultra
        • Samsung s21
        • Samsung s21 FE
        • Samsung s21 plus
        • Samsung s21 ultra
        • Samsung s22
        • Samsung s22 plus
        • Samsung s22 ultra
        • Samsung S23
        • Samsung S23 FE
        • Samsung S23 Plus
        • Samsung S23 Ultra
        • Samsung S24
        • Samsung S24 FE
        • Samsung S24 Plus
        • Samsung S24 Ultra
        • Samsung S25
        • Samsung S25 Edge
        • Samsung S25 FE
        • Samsung S25 Plus
        • Samsung S25 Ultra
        • Samsung S26
        • Samsung S26 Edge
        • Samsung S26 FE
        • Samsung S26 Plus
        • Samsung S26 Ultra
        • Samsung s4
        • Samsung s5
        • Samsung s6
        • Samsung s6 edge
        • Samsung s7
        • Samsung s7 edge
        • Samsung s8
        • Samsung s8 plus
        • Samsung s9
        • Samsung s9 plus
      • Samsung X cover model
        • Samsung x cover 3
        • Samsung x cover 4
        • Samsung x cover 4s
        • Samsung x cover 5
        • Samsung x cover 6 pro
        • Samsung X cover 7
        • Samsung x cover pro
      • Samsung Z Fold , Z flip models
        • Samsung Z Flip 3
        • Samsung Z Flip 4
        • Samsung Z flip 5
        • Samsung Z flip 6
        • Samsung Z flip 7
        • Samsung Z Fold 3
        • Samsung Z Fold 4
        • Samsung Z fold 5
        • Samsung Z fold 6
        • Samsung Z fold 7
  • Mobile, tablet , smart watches
    • Smart watches
  • Personal care, beauty and well-being
    • Hair dryer
    • Shaving and hair removal
  • Tempered Glass
    • Apple Watch
    • Ipad 3D
    • Iphone camera Lens
    • OG tempered Glass
      • Iphone
      • Samsung
    • Samsung camera lens
    • UV tempered Glass
      • Samsung
Login / Register
0 Wishlist
0 Compare
1 item / 999.00 kr
Menu
alibabatelecom
1 item / 999.00 kr
Browse Categories
  • Mobile, tablet , smart watches
    • Mobile
      • IOS Mobile
      • Android Mobile
      • Doro
    • Tablets
      • Ipad
      • Samsung TAB
    • Smart watches
Browse Categories
  • Apple
    • Iphone
      • Iphone 17 Pro Max
      • Iphone 17 Air
      • Iphone 17 Pro
      • Iphone 17e
      • Iphone 17
      • Iphone 16 Pro Max
      • Iphone 16 Plus
      • Iphone 16 Pro
      • Iphone 16e
      • Iphone 16
      • Iphone 15 Pro Max
      • Iphone 15 Plus
      • Iphone 15 Pro
      • Iphone 15
      • iphone 14 pro max
      • iphone 14 plus
      • iphone 14 pro
      • iphone 14
      • iphone 13 pro max
      • iphone 13 pro
      • iphone 13 mini
      • iphone 13
      • iphone 12 pro max
      • iphone 12 pro
      • iphone 12 mini
      • iphone 12
      • iphone 11 pro max
      • iphone 11 pro
      • iphone 11
      • iphone XS max
      • iphone XR
      • iphone XS
      • iphone X
      • iphone 8 plus
      • iphone 8
      • Iphone SE 2022
      • iphone SE 2020
      • iphone 7 plus
      • iphone 7
      • iphone 6s plus
      • iphone 6s
      • iphone 6 plus
      • Iphone 6
      • iphone SE
      • iphone 5S
      • iphone 5
    • IPad
      • iPad Pro 13 (2025)(13-inch (M5)
      • IPad Pro 13 (2024)(13-inch (M4)
      • iPad Pro 12.9 (6nd 2022)
      • iPad Pro 12.9 (5Gen 2021)
      • iPad Pro 12.9 (4Gen 2020)
      • iPad Pro 12.9 (3Gen 2018)
      • iPad Pro 12.9 (2Gen 2017)
      • iPad Pro 12.9 (1Gen 2015)
      • iPad Pro 11 (5 Gen: 2024) M4
      • iPad Pro 11 (4 Gen: 2022)
      • iPad Pro 11 (3Gen 2021)
      • iPad Pro 11 (2 Gen: 2020)
      • iPad Pro 11 (1Gen 2018)
      • iPad Pro 10.5 (2017)
      • iPad Pro 9.7 (2016)
      • iPad 10.9 (10th 2022)
      • iPad 10.2 9th Ge (2021)
      • iPad 10.2 8th Ge (2020)
      • iPad 10.2 7th Ge (2019)
      • iPad 9.7 (6th 2018)
      • iPad 9.7 (5th 2017)
      • iPad Air 13 (2024)
      • iPad Air 11 (2024) M2
      • iPad Air 5th Ge (2022)
      • iPad Air 4th Ge (2020)
      • iPad Air 3rd Ge (2019)
      • Ipad Air 2 (2014)
      • iPad Air (2013)
      • Ipad 4
      • Ipad 3
      • Ipad 2
      • Ipad mini 7th Ge (2023)
      • ipad mini 6th Ge (2021)
      • ipad mini 5th Ge (2019)
      • ipad mini 4th Ge (2015)
      • ipad mini 3rd Ge (2014)
      • ipad mini 2 (2013)
    • Apple Watch
      • Apple watch Ultra 49mm 2st Gen
      • Apple watch Ultra 49mm 1st Gen
      • Apple watch 9 serie 45mm
      • Apple watch 9 serie 41mm
      • Apple watch 8 serie 45mm
      • Apple watch 8 serie 41mm
      • Apple watch 7 serie 45mm
      • Apple watch 7 serie 41mm
      • Apple watch 6 serie 44mm
      • Apple watch 6 serie 40mm
      • Apple watch SE 2022 serie 44mm
      • Apple watch SE 2022 serie 40mm
      • Apple watch SE serie 44mm
      • Apple watch SE serie 40mm
      • Apple watch 5 serie 44mm
      • Apple watch 5 serie 40mm
      • Apple watch 4 serie 42mm
      • Apple watch 4 serie 38mm
      • Apple watch 3 serie 42mm
      • Apple watch 3 serie 40mm
    • AirPods
      • AirPods Pro (2st generation)
      • AirPods Pro (1st generation)
      • AirPods 4 (4st generation)
      • AirPods 3 (3st generation)
      • AirPods 2 (2st generation)
      • AirPods 1 (1st generation)
Browse Categories
  • Motorola
    • Moto G Models
      • Moto G200
      • Moto G100
      • Moto G85
      • Moto G84
      • Moto G82
      • Moto G75
      • Moto G73
      • Moto G72
      • Moto G71 5G
      • Moto G64
      • Moto G62
      • Moto G60s
      • Moto G60
      • Moto G56
      • Moto G55
      • Moto G54 Power
      • Moto G54
      • Moto G53
      • Moto G52
      • Moto G51 5G
      • Moto G50 5G
      • Moto G50 4G
      • Moto G45
      • Moto G42
      • Moto G41
      • Moto G35
      • Moto G34
      • Moto G32
      • Moto G31
      • Moto G30
      • Moto G24
      • Moto G23
      • Moto G22
      • Moto G20
      • Moto G15
      • Moto G14
      • Moto G13
      • Moto G10 play
      • Moto G10
      • Moto G Power (2021)
    • Moto E Models
      • Moto E40
      • Motorola Moto E32s
      • Motorola Moto E32
      • Motorola Moto E30
      • Motorola Moto E22
      • Motorola Moto E22i
      • Motorola Moto E20
      • Motorola Moto E14
      • Motorola Moto E15
      • Motorola Moto E13
Browse Categories
  • Accessories
    • Mouse , Keyboard
    • touch pen
    • Phone holder
    • phone card holder
    • Pop socket
    • USB-SD Memory card
    • Selfi
Browse Categories
  • Samsung
    • Samsung S model
      • Samsung S26 Ultra
      • Samsung S26 Plus
      • Samsung S26 Edge
      • Samsung S26 FE
      • Samsung S26
      • Samsung S25 Ultra
      • Samsung S25 Plus
      • Samsung S25 Edge
      • Samsung S25 FE
      • Samsung S25
      • Samsung S24 Ultra
      • Samsung S24 Plus
      • Samsung S24 FE
      • Samsung S24
      • Samsung S23 Ultra
      • Samsung S23 Plus
      • Samsung S23 FE
      • Samsung S23
      • Samsung s22 ultra
      • Samsung s22 plus
      • Samsung s22
      • Samsung s21 ultra
      • Samsung s21 plus
      • Samsung s21 FE
      • Samsung s21
      • Samsung s20 ultra
      • Samsung s20 plus
      • Samsung s20 FE
      • Samsung s20
      • Samsung s10 plus
      • Samsung S10 lite
      • Samsung s10e
      • Samsung s10
      • Samsung s9 plus
      • Samsung s9
      • Samsung s8 plus
      • Samsung s8
      • Samsung s7 edge
      • Samsung s7
      • Samsung s6 edge
      • Samsung s6
      • Samsung s5
      • Samsung s4
    • Samsung A model,
      • Samsung A90 (A908F)
      • Samsung A80 (A805F)
      • Samsung A73
      • Samsung A50 (A505F)
      • Samsung A72 (A725)
      • Samsung A71 5G (A716F)
      • Samsung A71 (A715F)
      • Samsung A70 (A705F)
      • Samsung A60 (A606F)
      • Samsung A56 (A566)
      • Samsung A55 (A556)
      • Samsung A54 (A546B)
      • Samsung A53 (A536B/DS)
      • Samsung A52s (A528B)
      • Samsung A52 (A525F)
      • Samsung A51 5G (A516B/DS)
      • Samsung A51 (A515F)
      • Samsung A50s
      • Samsung A42 (A426B)
      • Samsung A41 (A415F)
      • Samsung A40 (A405F)
      • Samsung A36 (A366)
      • Samsung A35 (A356)
      • |Samsung A34 (A346)
      • Samsung A33 5G (A336B)
      • Samsung A32 5G (A326)
      • Samsung A32 4G (A325)
      • Samsung A31 (A315F)
      • Samsung A30s (A307F)
      • Samsung A30 (A305F)
      • Samsung A26 (A266)
      • Samsung A25 (A256)
      • Samsung A24 (A245F)
      • Samsung A23 5G (SM-A236)
      • Samsung A23 4G (SM-A236)
      • Samsung A22 5G (A226B)
      • Samsung A22 4G (A225F)
      • Samsung A21s (A217F)
      • Samsung A21 (A215)
      • Samsung A20e (A202F)
      • Samsung A17
      • Samsung A16 5G (A166B)
      • Samsung A16 4G (A165F)
      • Samsung A15
      • Samsung A14 5G
      • Samsung A14 4G
      • Samsung A13 5G
      • Samsung A13 4G
      • Samsung A12
      • Samsung A11
      • Samsung A10s
      • Samsung A10
      • Samsung A07
      • Samsung A06
      • Samsung A05S
      • Samsung A04s
      • Samsung A03s
      • Samsung A03
      • samsung A02s
      • Samsung A02
      • Samsung A01
    • Samsung note model
      • Samsung Note 20 ultra
      • Samsung Note 20
      • Samsung Note 10 plus
      • Samsung Note 10 Lite
      • Samsung Note 10
      • Samsung Note 9
      • Samsung Note 8
      • Samsung Note 5
      • Samsung Note 4
    • Samsung X cover model
      • Samsung X cover 7
      • Samsung x cover 6 pro
      • Samsung x cover pro
      • Samsung x cover 5
      • Samsung x cover 4s
      • Samsung x cover 4
      • Samsung x cover 3
    • Samsung Z Fold , Z flip models
      • Samsung Z flip 7
      • Samsung Z flip 6
      • Samsung Z flip 5
      • Samsung Z Flip 4
      • Samsung Z Flip 3
      • Samsung Z fold 7
      • Samsung Z fold 7 FE
      • Samsung Z fold 6
      • Samsung Z fold 5
      • Samsung Z Fold 4
      • Samsung Z Fold 3
  • Samsung TAB models
  • Samsung TAB A series
  • Samsung TAB S Series
  • Samsung TAB E series
Browse Categories
  • Personal care, beauty and well-being
    • Hair dryer
    • Shaving and hair removal
Browse Categories
  • Huawei
    • Huawei P Models
      • Huawei P40 pro
      • Huawei P40 Lite
      • Huawei P40
      • Huawei P30 Pro
      • Huawei P30 Lite
      • Huawei P30
      • Huawei P20 Pro
      • Huawei P20 Lite 2019
      • Huawei P20 Lite
      • Huawei P20
      • Huawei P10 Lite
      • Huawei P10
      • Huawei P9 Lite
      • Huawei P9
      • Huawei P8 Lite
      • Huawei P8
      • Huawei P7
    • Huawei Mate Models
      • Huawei Mate 40 Pro
      • Huawei Mate 40
      • Huawei Mate 30 Pro
      • Huawei Mate 30 Lite
      • Huawei Mate 30
      • Huawei Mate 20 Pro
      • Huawei Mate 20 Lite
      • Huawei Mate 20
      • Huawei Mate 10 Pro
      • Huawei Mate 10 Lite
      • Huawei Mate 10
      • Huawei Mate 9 pro
      • Huawei Mate 9
      • Huawei Mate 8
      • Huawei Mate 7
    • Huawei P smart Models
      • Huawei P smart 2021
      • Huawei P smart 2020
      • Huawei P smart 2019
      • Huawei P smart pro
      • Huawei P smart Z
    • Huawei Honor Models
      • Huawei Honor 20 Pro
      • Huawei Honor 20 Lite
      • Huawei Honor View 20
      • Huawei Honor 20
      • Huawei Honor View 10
      • Huawei Honor 10
      • Huawei Honor 9
      • Huawei Honor 8 Lite
      • Huawei Honor 8
      • Huawei Honor 7
      • Huawei Honor 6
Browse Categories
  • Electronics
    • Headset , audio jack
    • Adapters
    • Cables
    • Car adapter , cables
    • Wirless charger
    • Bluetooth Speaker
    • HDMI , converter
    • Oudio Other
    • Gaming
    • Internet cables
    • Power bank
Browse Categories
  • Tempered Glass
    • OG tempered Glass
      • Iphone
      • Samsung
    • UV tempered Glass
      • Samsung
      • Huawei
    • Iphone camera Lens
    • Samsung camera lens
    • Ipad 3D
    • Samsung TAB
    • Apple Watch
    • Samsung watch
Browse Categories
  • Childeren toys
    • Car , Motor
Reparation
  • Home
  • Electronics
  • Mobile, tablet , smart watches
  • Repare Phone Price
  • Accessories
  • Tempered Glass
“Iphone 12 Pro Front Camera” has been added to your cart. View cart
Ipad Air 2 charging flix
Click to enlarge
HomeMobile , Tablets AccessoriesSamsungSamsung Buds case Ipad Air 2 charging flix
Previous product
Ipad Air charging flix
Ipad Air charging flix 999.00 kr
Back to products
Next product
Ipad Air ( 2 ) battery
Ipad Air ( 2 ) battery 1,199.00 kr

Ipad Air 2 charging flix

149.00 kr

Charging flex cable for iPad Air 2

Model : ( A1566 , A1567 )

4 in stock

Compare
Add to wishlist
SKU: UTT8358645 Category: Samsung Buds case Tag: Apple
  • Description
  • Shipping & Delivery
Description

Charging flex cable for iPad Air 2

Model : ( A1566 , A1567 )

Shipping & Delivery

MAECENAS IACULIS

Vestibulum curae torquent diam diam commodo parturient penatibus nunc dui adipiscing convallis bulum parturient suspendisse parturient a.Parturient in parturient scelerisque nibh lectus quam a natoque adipiscing a vestibulum hendrerit et pharetra fames nunc natoque dui.

ADIPISCING CONVALLIS BULUM

  • Vestibulum penatibus nunc dui adipiscing convallis bulum parturient suspendisse.
  • Abitur parturient praesent lectus quam a natoque adipiscing a vestibulum hendre.
  • Diam parturient dictumst parturient scelerisque nibh lectus.

Scelerisque adipiscing bibendum sem vestibulum et in a a a purus lectus faucibus lobortis tincidunt purus lectus nisl class eros.Condimentum a et ullamcorper dictumst mus et tristique elementum nam inceptos hac parturient scelerisque vestibulum amet elit ut volutpat.

Related products

Compare
Quick view
Add to wishlist
Close

Iphone 8 , SE 2020 , SE 2022 Charging cable

Only 1 left in stock
599.00 kr
Select options
Compare
Quick view
Add to wishlist
Close

Iphone 11 Pro Max Front Camera

3 left in stock
699.00 kr
Add to cart
Compare
Quick view
Add to wishlist
Close

Iphone 7 AAA Display

43 left in stock
799.00 kr
Select options
Compare
Quick view
Add to wishlist
Close

Iphone 12 Front Camera

Only 2 left in stock
999.00 kr
Add to cart
Iphone 7 Plus AAA Display
Compare
Quick view
Add to wishlist
Close

Iphone 7 Plus DA best Display

23 left in stock
899.00 kr
Select options
Compare
Quick view
Add to wishlist
Close

Iphone 7 Plus DA best Display

22 left in stock
899.00 kr
Select options
Iphone 8 Plus AAA Display
Compare
Quick view
Add to wishlist
Close

Iphone 8 Plus DA best Display

12 left in stock
899.00 kr
Select options
Compare
Quick view
Add to wishlist
Close

Iphone 12 Pro Front Camera

Only 1 left in stock
999.00 kr
Add to cart
Samsung
OG
Luxury clear magnetic
IDEAL OF SWEDEN
Hoco
Gorilla Anti-Shock
Fashion
Celly Hello world
BOROFONE
Apple
AMA Extra pas
AMA
Adidas

Vi startet reisen vår i 2017, da etterspørselen etter reparasjoner og reservedeler til mobiltelefoner og nettbrett økte betraktelig. Alibaba Telecom AS åpnet sin første butikk på AMFI sentrum i Larvik og videre åpnet nye avdelinger i forskjellige byer. Alibaba Telecom AS ble en av de største leverandøren i Norden, med et stort lager på mer enn 100 000 høykvalitetsprodukter. .

Storgata 107, 3921 Porsgrunn, Norway
Phone: (0047) 48473337
Phone: (0047) 41201616
Recent Posts
  • Protected: drammen
    December 12, 2022 No Comments
  • Protected: stathelle
    December 12, 2022 No Comments
Useful links
  • ALIBABA TELECOM
  • Electronics
  • Accessories
  • Contact Us
  • Abuot US
Footer Menu
  • Home
  • reparation
  • faq
  • Contact Us
  • abute us
  • Shop
Hinet.co 2022 All rights of this website belong to alibabatelecom
payments
  • Home
  • Electronics
  • Mobile, tablet , smart watches
  • Repare Phone Price
  • Accessories
  • Tempered Glass
Shopping cart
close
Select your currency
NOK Norwegian krone
USD United States (US) dollar
EUR Euro

Sign in

close

Lost your password?

No account yet?

Create an Account