diff --git a/includes/admin/core/class-admin-menu.php b/includes/admin/core/class-admin-menu.php index 03058af9..4cb0e349 100644 --- a/includes/admin/core/class-admin-menu.php +++ b/includes/admin/core/class-admin-menu.php @@ -223,7 +223,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { add_meta_box( 'um-metaboxes-sidebox-2', __( 'User Cache', 'ultimate-member' ), array( &$this, 'user_cache' ), $this->pagehook, 'side', 'core' ); //If there are active and licensed extensions - show metabox for upgrade it - $exts = UM()->plugin_updater()->um_get_active_plugins(); + $exts = UM()->plugin_updater()->get_active_plugins(); if ( 0 < count( $exts ) ) { add_meta_box( 'um-metaboxes-sidebox-3', __( 'Upgrade\'s Manual Request', 'ultimate-member' ), array( &$this, 'upgrade_request' ), $this->pagehook, 'side', 'core' ); } diff --git a/includes/admin/core/class-admin-notices.php b/includes/admin/core/class-admin-notices.php index 4bf21ec6..0302d30e 100644 --- a/includes/admin/core/class-admin-notices.php +++ b/includes/admin/core/class-admin-notices.php @@ -534,7 +534,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { if ( ! empty( $arr_inactive_license_keys ) ) { $this->add_notice( 'license_key', array( 'class' => 'error', - 'message' => '
' . sprintf( __( 'There are %d inactive %s license keys for this site. This site is not authorized to get plugin updates. You can active this site on www.ultimatemember.com.', 'ultimate-member' ), count( $arr_inactive_license_keys ) , ultimatemember_plugin_name, 'https://ultimatemember.com' ) . '
', + 'message' => '' . sprintf( __( 'There are %d inactive %s license keys for this site. This site is not authorized to get plugin updates. You can active this site on www.ultimatemember.com.', 'ultimate-member' ), count( $arr_inactive_license_keys ) , ultimatemember_plugin_name, UM()->store_url ) . '
', ), 3 ); } diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index 187f5d8c..08e3f58e 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -1703,9 +1703,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { ); $request = wp_remote_post( - 'https://ultimatemember.com/', + UM()->store_url, array( - 'timeout' => 15, + 'timeout' => UM()->request_timeout, 'sslverify' => false, 'body' => $api_params ) diff --git a/includes/class-functions.php b/includes/class-functions.php index c31b7698..6048898c 100644 --- a/includes/class-functions.php +++ b/includes/class-functions.php @@ -10,6 +10,21 @@ if ( ! class_exists( 'UM_Functions' ) ) { class UM_Functions { + /** + * Store URL + * + * @var string + */ + var $store_url = 'https://ultimatemember.com/'; + + + /** + * WP remote Post timeout + * @var int + */ + var $request_timeout = 60; + + /** * UM_Functions constructor. */ diff --git a/includes/core/class-files.php b/includes/core/class-files.php index e3a0ed6d..1733a3cd 100644 --- a/includes/core/class-files.php +++ b/includes/core/class-files.php @@ -171,7 +171,8 @@ if ( ! class_exists( 'um\core\Files' ) ) { } } - if ( validate_file( $file_path ) !== 0 ) { + //validate traversal file + if ( validate_file( $file_path ) === 1 ) { return; } @@ -215,7 +216,8 @@ if ( ! class_exists( 'um\core\Files' ) ) { } } - if ( validate_file( $file_path ) !== 0 ) { + //validate traversal file + if ( validate_file( $file_path ) === 1 ) { return; } diff --git a/includes/core/class-plugin-updater.php b/includes/core/class-plugin-updater.php index 3fdecbfd..0523ba85 100644 --- a/includes/core/class-plugin-updater.php +++ b/includes/core/class-plugin-updater.php @@ -25,14 +25,14 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { register_deactivation_hook( um_plugin, array( &$this, 'um_plugin_updater_deactivation_hook' ) ); - //cron request to ultimatemember.com + //cron request to UM()->store_url; add_action( 'um_check_extensions_licenses', array( &$this, 'um_checklicenses' ) ); //update plugin info - add_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'um_check_update' ) ); + add_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'check_update' ) ); //plugin information info - add_filter( 'plugins_api', array( &$this, 'um_plugins_api_filter' ), 9999, 3 ); + add_filter( 'plugins_api', array( &$this, 'plugin_information' ), 9999, 3 ); } @@ -41,7 +41,7 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { * * @return array */ - function um_get_active_plugins() { + function get_active_plugins() { $paid_extensions = array( 'um-bbpress/um-bbpress.php' => array( 'key' => 'bbpress', @@ -179,8 +179,9 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { if ( in_array( $value, array_keys( $paid_extensions ) ) ) { $license = UM()->options()->get( "um_{$paid_extensions[ $value ]['key']}_license_key" ); - if ( empty( $license ) ) + if ( empty( $license ) ) { continue; + } $active_um_plugins[ $value ] = $paid_extensions[ $value ]; $active_um_plugins[ $value ]['license'] = $license; @@ -204,7 +205,7 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { * Check license function */ function um_checklicenses() { - $exts = $this->um_get_active_plugins(); + $exts = $this->get_active_plugins(); if ( 0 == count( $exts ) ) { return; @@ -232,49 +233,68 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { } $request = wp_remote_post( - 'https://ultimatemember.com/', + UM()->store_url, array( - 'timeout' => 45, + 'timeout' => UM()->request_timeout, 'sslverify' => false, 'body' => $api_params ) ); - if ( ! is_wp_error( $request ) ) + if ( ! is_wp_error( $request ) ) { $request = json_decode( wp_remote_retrieve_body( $request ) ); + } $request = ( $request ) ? maybe_unserialize( $request ) : false; if ( $request ) { foreach ( $exts as $slug => $data ) { - if ( ! empty( $request->$slug->license_check ) ) + if ( ! empty( $request->$slug->license_check ) ) { update_option( "{$data['key']}_edd_answer", $request->$slug->license_check ); + } if ( ! empty( $request->$slug->get_version_check ) ) { $request->$slug->get_version_check = json_decode( $request->$slug->get_version_check ); - if ( ! empty( $request->$slug->get_version_check->package ) ) + if ( ! empty( $request->$slug->get_version_check->package ) ) { $request->$slug->get_version_check->package = $this->extend_download_url( $request->$slug->get_version_check->package, $slug, $data ); + } - if ( ! empty( $request->$slug->get_version_check->download_link ) ) + if ( ! empty( $request->$slug->get_version_check->download_link ) ) { $request->$slug->get_version_check->download_link = $this->extend_download_url( $request->$slug->get_version_check->download_link, $slug, $data ); + } if ( isset( $request->$slug->get_version_check->sections ) ) { $request->$slug->get_version_check->sections = maybe_unserialize( $request->$slug->get_version_check->sections ); - $request->$slug->get_version_check = json_encode( $request->$slug->get_version_check ); + $request->$slug->get_version_check->sections = (array) $request->$slug->get_version_check->sections; } else { $request->$slug->get_version_check = new \WP_Error( 'plugins_api_failed', sprintf( /* translators: %s: support forums URL */ - __( 'An unexpected error occurred. Something may be wrong with https://ultimatemember.com/ or this server’s configuration. If you continue to have problems, please try the support forums.' ), + __( 'An unexpected error occurred. Something may be wrong with %s or this server’s configuration. If you continue to have problems, please try the support forums.' ), + UM()->store_url, __( 'https://wordpress.org/support/' ) ), wp_remote_retrieve_body( $request->$slug->get_version_check ) ); } - update_option( "{$data['key']}_version_check_edd_answer", $request->$slug->get_version_check ); + if ( isset( $request->$slug->get_version_check->banners ) ) { + $request->$slug->get_version_check->banners = maybe_unserialize( $request->$slug->get_version_check->banners ); + } + + if ( isset( $request->$slug->get_version_check->icons ) ) { + $request->$slug->get_version_check->icons = maybe_unserialize( $request->$slug->get_version_check->icons ); + } + + if ( ! empty( $request->$slug->get_version_check->sections ) ) { + foreach( $request->$slug->get_version_check->sections as $key => $section ) { + $request->$slug->get_version_check->$key = (array) $section; + } + } + + $this->set_version_info_cache( $slug, $request->$slug->get_version_check ); } } } @@ -290,31 +310,45 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { * @param array $_transient_data plugin update array build by WordPress. * @return \stdClass modified plugin update array. */ - function um_check_update( $_transient_data ) { + function check_update( $_transient_data ) { global $pagenow; - if ( ! is_object( $_transient_data ) ) + if ( ! is_object( $_transient_data ) ) { $_transient_data = new \stdClass; + } - if ( 'plugins.php' == $pagenow && is_multisite() ) + if ( 'plugins.php' == $pagenow && is_multisite() ) { return $_transient_data; + } + + $exts = $this->get_active_plugins(); - $exts = $this->um_get_active_plugins(); foreach ( $exts as $slug => $data ) { + //if response for current product isn't empty check for override + if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $slug ] ) && $_transient_data->last_checked > time() - DAY_IN_SECONDS ) { + continue; + } $plugin_data = get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $slug ); - //if response for current product isn't empty check for override - if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $slug ] ) ) - continue; + $version_info = $this->get_cached_version_info( $slug ); + if ( false === $version_info ) { + $version_info = $this->single_request( 'plugin_latest_version', array( + 'slug' => $slug, + 'license' => $data['license'], + 'item_name' => $data['title'], + 'version' => $plugin_data['Version'] + ) ); - $version_info = get_option( "{$data['key']}_version_check_edd_answer" ); - $version_info = json_decode( $version_info ); + $this->set_version_info_cache( $slug, $version_info ); + } if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) { //show update version block if new version > then current - if ( version_compare( $plugin_data['Version'], $version_info->new_version, '<' ) ) + if ( version_compare( $plugin_data['Version'], $version_info->new_version, '<' ) ) { $_transient_data->response[ $slug ] = $version_info; + $_transient_data->response[ $slug ]->plugin = $slug; + } $_transient_data->last_checked = time(); $_transient_data->checked[ $slug ] = $plugin_data['Version']; @@ -326,6 +360,74 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { } + + /** + * Calls the API and, if successfull, returns the object delivered by the API. + * + * @uses get_bloginfo() + * @uses wp_remote_post() + * @uses is_wp_error() + * + * @param string $_action The requested action. + * @param array $_data Parameters for the API action. + * @return false|object + */ + private function single_request( $_action, $_data ) { + $api_params = array( + 'edd_action' => 'get_version', + 'author' => 'Ultimate Member', + 'url' => home_url(), + 'beta' => false, + ); + + $api_params = array_merge( $api_params, $_data ); + + $request = wp_remote_post( + UM()->store_url, + array( + 'timeout' => UM()->request_timeout, + 'sslverify' => false, + 'body' => $api_params + ) + ); + + if ( ! is_wp_error( $request ) ) { + $request = json_decode( wp_remote_retrieve_body( $request ) ); + } + + if ( $request && isset( $request->sections ) ) { + $request->sections = maybe_unserialize( $request->sections ); + $request->sections = (array) $request->sections; + } else { + $request = false; + } + + if ( $request && isset( $request->banners ) ) { + $request->banners = maybe_unserialize( $request->banners ); + } + + if ( $request && isset( $request->icons ) ) { + $request->icons = maybe_unserialize( $request->icons ); + } + + if( ! empty( $request->sections ) ) { + foreach ( $request->sections as $key => $section ) { + $request->$key = (array) $section; + } + } + + if ( ! empty( $request->package ) ) { + $request->package = $this->extend_download_url( $request->package, $_data['slug'], $_data ); + } + + if ( ! empty( $request->download_link ) ) { + $request->download_link = $this->extend_download_url( $request->download_link, $_data['slug'], $_data ); + } + + return $request; + } + + /** * Updates information on the "View version x.x details" popup with custom data. * @@ -334,27 +436,37 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { * @param object $_args * @return object $_data */ - function um_plugins_api_filter( $_data, $_action = '', $_args = null ) { + function plugin_information( $_data, $_action = '', $_args = null ) { //by default $data = false (from Wordpress) - - if ( $_action != 'plugin_information' ) + if ( $_action != 'plugin_information' ) { return $_data; + } - $exts = $this->um_get_active_plugins(); - + $exts = $this->get_active_plugins(); foreach ( $exts as $slug => $data ) { - if ( isset( $_args->slug ) && $_args->slug == $slug ) - $api_request_transient = get_option( "{$data['key']}_version_check_edd_answer" ); + if ( isset( $_args->slug ) && $_args->slug == $slug ) { + $api_request_transient = $this->get_cached_version_info( $slug ); + + if ( false === $api_request_transient ) { + $plugin_data = get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $slug ); + + $api_request_transient = $this->single_request( 'plugin_latest_version', array( + 'slug' => $slug, + 'license' => $data['license'], + 'item_name' => $data['title'], + 'version' => $plugin_data['Version'] + ) ); + $this->set_version_info_cache( $slug, $api_request_transient ); + } + break; + } } //If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now. - if ( ! empty( $api_request_transient ) ) { - $_data = json_decode( $api_request_transient ); + if ( isset( $api_request_transient ) ) { + $_data = $api_request_transient; } - if ( isset( $_data->sections ) ) - $_data->sections = (array)$_data->sections; - return $_data; } @@ -405,6 +517,73 @@ if ( ! class_exists( 'um\core\Plugin_Updater' ) ) { return $download_url; } + + + /** + * @param $slug + * + * @return bool|string + */ + function get_cache_key( $slug ) { + $exts = $this->get_active_plugins(); + + if ( empty( $exts[ $slug ] ) ) { + return false; + } + + return 'edd_sl_' . md5( serialize( $slug . $exts[ $slug ]['license'] ) ); + } + + + /** + * @param $slug + * + * @return array|bool|mixed|object + */ + function get_cached_version_info( $slug ) { + $cache_key = $this->get_cache_key( $slug ); + if ( empty( $cache_key ) ) { + return false; + } + + $cache = get_option( $cache_key ); + if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) { + return false; // Cache is expired + } + + // We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point. + $cache['value'] = json_decode( $cache['value'] ); + if ( ! empty( $cache['value']->icons ) ) { + $cache['value']->icons = (array) $cache['value']->icons; + } + if ( ! empty( $cache['value']->sections ) ) { + $cache['value']->sections = (array) $cache['value']->sections; + } + if ( ! empty( $cache['value']->banners ) ) { + $cache['value']->banners = (array) $cache['value']->banners; + } + + return $cache['value']; + } + + + /** + * @param $slug + * @param string $value + */ + function set_version_info_cache( $slug, $value = '' ) { + $cache_key = $this->get_cache_key( $slug ); + if ( empty( $cache_key ) ) { + return; + } + + $data = array( + 'timeout' => strtotime( '+6 hours', time() ), + 'value' => json_encode( $value ) + ); + + update_option( $cache_key, $data, 'no' ); + } } } \ No newline at end of file diff --git a/includes/core/class-uploader.php b/includes/core/class-uploader.php index 3eb3166a..8490e772 100644 --- a/includes/core/class-uploader.php +++ b/includes/core/class-uploader.php @@ -1151,8 +1151,17 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { $old_filename = get_user_meta( $user_id, $key, true ); if ( ! empty( $old_filename ) ) { $file = $user_basedir . DIRECTORY_SEPARATOR . $old_filename; - if ( file_exists( $file ) ) { - unlink( $file ); + + $valid = true; + //validate traversal file + if ( validate_file( $file ) === 1 ) { + $valid = false; + } + + if ( $valid ) { + if ( file_exists( $file ) && um_is_file_owner( $file, $user_id ) ) { + unlink( $file ); + } } } diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index a962cf99..ed096d59 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -271,6 +271,8 @@ function um_user_edit_profile( $args ) { if ( /*um_is_file_owner( UM()->uploader()->get_upload_base_url() . um_user( 'ID' ) . '/' . $args['submitted'][ $key ], um_user( 'ID' ) ) ||*/ um_is_temp_file( $args['submitted'][ $key ] ) || $args['submitted'][ $key ] == 'empty_file' ) { $files[ $key ] = $args['submitted'][ $key ]; + } elseif( um_is_file_owner( UM()->uploader()->get_upload_base_url() . um_user( 'ID' ) . '/' . $args['submitted'][ $key ], um_user( 'ID' ) ) ) { + /*$files[ $key ] = 'empty_file';*/ } else { $files[ $key ] = 'empty_file'; } @@ -403,6 +405,8 @@ function um_user_edit_profile( $args ) { * } * ?> */ + /*var_dump( $files ); + exit;*/ $files = apply_filters( 'um_user_pre_updating_files_array', $files ); if ( ! empty( $files ) && is_array( $files ) ) { @@ -463,6 +467,9 @@ function um_user_edit_profile( $args ) { add_action( 'um_user_edit_profile', 'um_user_edit_profile', 10 ); +add_filter( 'um_user_pre_updating_files_array', array( UM()->validation(), 'validate_files' ), 10, 1 ); +add_filter( 'um_before_save_filter_submitted', array( UM()->validation(), 'validate_fields_values' ), 10, 2 ); + /** * Leave roles for User, which are not in the list of update profile (are default WP or 3rd plugins roles) * diff --git a/ultimate-member.php b/ultimate-member.php index db436234..48093caf 100644 --- a/ultimate-member.php +++ b/ultimate-member.php @@ -3,7 +3,7 @@ Plugin Name: Ultimate Member Plugin URI: http://ultimatemember.com/ Description: The easiest way to create powerful online communities and beautiful user profiles with WordPress -Version: 2.0.46-beta1 +Version: 2.0.46-beta3 Author: Ultimate Member Author URI: http://ultimatemember.com/ Text Domain: ultimate-member