diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/_mediavault.php b/_mediavault.php new file mode 100644 index 0000000..f2b8886 --- /dev/null +++ b/_mediavault.php @@ -0,0 +1,1271 @@ + array( + 'description' => __( 'Admin users only', 'media-vault' ), + 'select' => __( 'Admin users', 'media-vault' ), + 'logged_in' => true, + 'run_in_admin' => true, + 'cb' => 'mgjp_mv_check_admin_permission' + ), + 'author' => array( + 'description' => __( 'The file\'s author', 'media-vault' ), + 'select' => __( 'The file\'s author', 'media-vault' ), + 'logged_in' => true, + 'run_in_admin' => true, + 'cb' => 'mgjp_mv_check_author_permission' + ), + 'logged-in' => array( + 'description' => __( 'All logged-in users', 'media-vault' ), + 'select' => __( 'Logged-in users', 'media-vault' ), + 'logged_in' => true, + 'run_in_admin' => false, + 'cb' => false + ), + 'all' => array( + 'description' => __( 'Anyone', 'media-vault' ), + 'select' => __( 'Anyone', 'media-vault' ), + 'logged_in' => false, + 'run_in_admin' => false, + 'cb' => false + ) +); + + +register_activation_hook( __FILE__, 'mgjp_mv_activate' ); +register_deactivation_hook( __FILE__, 'mgjp_mv_deactivate' ); + +add_action( 'plugins_loaded', 'mgjp_mv_textdomain' ); + +add_action( 'init', 'mgjp_mv_check_version' ); + +add_action( 'load-plugins.php', 'mgjp_mv_on_deactivation_request' ); + +if ( get_site_option( 'mgjp_mv_enabled' ) ) { + + add_action( 'init', 'mgjp_mv_handle_file_request', 0 ); + add_action( 'init', 'mgjp_mv_register_shortcodes' ); + + add_action( 'wp_enqueue_media', 'mgjp_mv_attachment_edit_fields_styles_and_scripts' ); + + add_filter( 'mod_rewrite_rules', 'mgjp_mv_add_plugin_rewrite_rules' ); + + add_filter( 'upload_dir', 'mgjp_mv_change_upload_directory', 999 ); + + add_filter( 'user_has_cap', 'mgjp_mv_edit_capabilities', 999, 3 ); + + add_filter( 'image_downsize', 'mgjp_mv_replace_protected_image', 999, 3 ); + + if ( is_admin() ) { + + add_action( 'admin_init', 'mgjp_mv_ajax_actions_include', 0 ); + add_action( 'admin_init', 'mgjp_mv_media_vault_options_include' ); + add_action( 'admin_init', 'mgjp_mv_attachment_metabox_include' ); + + add_action( 'load-media-new.php', 'mgjp_mv_media_new_options_include' ); + add_action( 'load-upload.php', 'mgjp_mv_media_library_options_include' ); + + add_filter( 'admin_body_class', 'mgjp_add_mp6_admin_body_class' ); + + add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'mgjp_mv_settings_link' ); + + } + +} else { + + include( plugin_dir_path( __FILE__ ) . 'mv-extra-activation-steps.php' ); + +} + +if ( get_site_option( 'mgjp_mv_deactivation' ) ) + include( plugin_dir_path( __FILE__ ) . 'mv-extra-deactivation-steps.php' ); + + +//-----------------------------------------------------------------------// +// MEDIA VAULT - PERMISSION CHECKING FUNCTIONS +//-----------------------------------------------------------------------// + + +/** + * The 'admin' permission checking callback. + * + * @since 0.4 + */ +function mgjp_mv_check_admin_permission() { + if ( ! current_user_can( 'manage_options' ) ) + return new WP_Error( 'not_admin', __( 'You do not have sufficient permissions to view this file.', 'media-vault' ) ); + + return true; +} + +/** + * The 'author' permission checking callback. + * + * @since 0.4 + */ +function mgjp_mv_check_author_permission( $attachment_id ) { + + if ( current_user_can( 'manage_options' ) ) + return true; + + if ( ! isset( $attachment_id ) || empty( $attachment_id ) ) + return new WP_Error( 'no_id', __( 'There was an error determining this attachment\'s author. Please contact the website administrator.', 'media-vault' ) ); + + if ( get_current_user_id() != get_post_field( 'post_author', $attachment_id, 'raw' ) ) + return new WP_Error( 'not_author', __( 'You do not have sufficient permissions to view this file.', 'media-vault' ) ); + + return true; +} + + + +//-----------------------------------------------------------------------// +// MEDIA VAULT - MAIN HOOKED FUNCTIONS +//-----------------------------------------------------------------------// + + +/** + * On plugin activation + * + * @since 0.1 + * + * @uses _mgjp_mv_activate_local() + */ +function mgjp_mv_activate( $network_activating ) { + + global $is_apache; + + if ( $is_apache + && ! is_multisite() + && get_option( 'permalink_structure' ) + && got_mod_rewrite() + && is_writable( get_home_path() . '.htaccess' ) ) { + + // register plugin enabled option + update_site_option( 'mgjp_mv_enabled', true ); + + // Flush rewrite rules to add Media Vault rewrite rules to the + // site's .htaccess file on plugin activation + add_filter( 'mod_rewrite_rules', 'mgjp_mv_add_plugin_rewrite_rules' ); + flush_rewrite_rules(); + } + + // register Media Vault's other network-wide options + add_site_option( 'mgjp_mv_version', MGJP_MV_VERSION, '', 'yes' ); + delete_site_option( 'mgjp_mv_deactivation' ); + + if ( ! is_multisite() ) { + + // run the activation function for the single site + _mgjp_mv_activate_local(); + + } else if ( ! wp_is_large_network() ) { + global $wpdb; + + $blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ); + + // run the activation function for each site in the network + foreach ( $blog_ids as $blog_id ) { + + switch_to_blog( $blog_id ); + _mgjp_mv_activate_local( $blog_id ); + restore_current_blog(); + + } + } +} + + +/** + * On plugin deactivation + * + * @since 0.1 + * + * @uses mgjp_mv_check_rewrite_rules() + */ +function mgjp_mv_deactivate( $network_deactivating ) { + + delete_site_option( 'mgjp_mv_deactivation' ); + delete_site_option( 'mgjp_mv_enabled' ); + + // Flush rewrite rules to remove Media Vault rewrite rules from the + // site's .htaccess file on plugin deactivation + remove_filter( 'mod_rewrite_rules', 'mgjp_mv_add_plugin_rewrite_rules' ); + flush_rewrite_rules(); + + if ( ! is_multisite() ) { + + // run the deactivation function for the single site + _mgjp_mv_deactivate_local(); + + } else if ( ! wp_is_large_network() ) { + global $wpdb; + + $blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ); + + // run the deactivation function for each site in the network + foreach ( $blog_ids as $blog_id ) { + + switch_to_blog( $blog_id ); + _mgjp_mv_deactivate_local( $blog_id ); + restore_current_blog(); + + } + } +} + + +/** + * Load the plugin textdomain. + * + * @since 0.1 + */ +function mgjp_mv_textdomain() { + + load_plugin_textdomain( 'media-vault', false, plugin_dir_path( __FILE__ ) . 'languages/' ); + +} + + +/** + * Plugin update handling. Checks current version against + * a version number stored in the database and performs any + * necessary upgrades using the MGJP_MV_Update class + * + * @since 0.8 + * + * @uses MGJP_MV_Update + */ +function mgjp_mv_check_version() { + + $option_key = 'mgjp_mv_version'; + + $version_db = get_site_option( $option_key, '0' ); + + if ( version_compare( $version_db, MGJP_MV_VERSION, 'eq' ) ) + return; + + if ( version_compare( $version_db, MGJP_MV_VERSION, 'gt' ) ) + return update_site_option( $option_key, MGJP_MV_VERSION ); + + include( plugin_dir_path( __FILE__ ) . 'mv-class-update.php' ); + + if ( class_exists( 'MGJP_MV_Update' ) ) + new MGJP_MV_Update( $version_db, MGJP_MV_VERSION, $option_key ); + +} + + +/** + * Remove Media Vault from the plugins.php deactivation + * actions if Media Vault needs extra steps in order + * to deactivate + * + * @since 0.8.5 + * + * @uses mgjp_mv_get_dirfile() + * @uses mgjp_mv_is_deactivation_allowed() + */ +function mgjp_mv_on_deactivation_request() { + + if ( in_array( get_site_option( 'mgjp_mv_deactivation' ), array( 'allowed', 'temp' ) ) ) + return; + + $action = isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ? + $_REQUEST['action'] : + ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ? + $_REQUEST['action2'] : + false + ); + + if ( ! in_array( $action, array( 'deactivate', 'deactivate-selected' ) ) ) + return; + + switch ( $action ) { + case 'deactivate': + if ( ! isset( $_REQUEST['plugin'] ) || mgjp_mv_get_dirfile() != $_REQUEST['plugin'] ) + return; + + if ( mgjp_mv_is_deactivation_allowed() ) + return; + + update_site_option( 'mgjp_mv_deactivation', 'disallowed' ); + + $location = remove_query_arg( array( 'action', 'plugin', '_wpnonce' ), $_SERVER['REQUEST_URI'] ); + wp_redirect( $location ); + exit; + break; + case 'deactivate-selected': + $plugin_dirfile = mgjp_mv_get_dirfile(); + + if ( ! isset( $_POST['checked'] ) || ! in_array( $plugin_dirfile, (array) $_POST['checked'] ) ) + return; + + if ( mgjp_mv_is_deactivation_allowed() ) + return; + + update_site_option( 'mgjp_mv_deactivation', 'disallowed' ); + + $_POST['checked'] = array_diff( $_POST['checked'], array( $plugin_dirfile ) ); + break; + } +} + + +/** + * Trigger protected media uploads file handling function + * if 'file' GET parameter is set in URL on wp init + * + * @since 0.1 + * + * @uses mgjp_mv_get_file() + */ +function mgjp_mv_handle_file_request() { + + if ( isset( $_GET['mgjp_mv_file'] ) && ! empty( $_GET['mgjp_mv_file'] ) ) { + + // used by @func mgjp_mv_check_rewrite_rules to verify rewrite rules are + // set and working as intended + if ( isset( $_GET['mgjp_mv_rewrite_test'] ) && $_GET['mgjp_mv_rewrite_test'] ) + die( 'pass' ); + + require( plugin_dir_path( __FILE__ ) . 'mv-file-handler.php' ); + + // Check if force download flag is set + $force_download = isset( $_REQUEST['mgjp_mv_download'] ) ? + $_REQUEST['mgjp_mv_download'] : + ''; + + if ( function_exists( 'mgjp_mv_get_file' ) ) { + mgjp_mv_get_file( $_GET['mgjp_mv_file'], $force_download ); + exit; // This exit is important as all we want to do when a + // media download is requested is to serve it and exit + // If it is missing WP will continue serving the page + // after the media file, thus breaking it + } + } +} + + +/** + * Register Media Vault Shortcodes + * + * @since 0.5 + */ +function mgjp_mv_register_shortcodes() { + + include( plugin_dir_path( __FILE__ ) . 'mv-shortcodes.php' ); + + if ( function_exists( 'mgjp_mv_download_links_list_shortcode_handler' ) ) + add_shortcode( 'mv_dl_links', 'mgjp_mv_download_links_list_shortcode_handler' ); + +} + + +/** + * Enqueue styles and scripts for Media Vault + * attachment edit fields. + * + * @hook action 'wp_enqueue_media' + * + * @since 0.8.8 + */ +function mgjp_mv_attachment_edit_fields_styles_and_scripts() { + + wp_enqueue_style( 'mgjp-mv-att-fields-css', plugins_url( 'css/mv-attachment-fields.css', __FILE__ ), 'all', null ); + wp_enqueue_script( 'mgjp-mv-att-fields-js', plugins_url( 'js/min/mv-attachment-fields.min.js', __FILE__ ), array( 'media-editor' ), null, true ); + +} + + +/** + * Add the plugin rewrite rules to the WP rewrite + * rules being written in the sitewide .htaccess file + * + * @since 0.8.5 + * + * @uses mgjp_mv_get_the_rewrite_rules() + * @param $rules string String containing all rewrite rules to be written in htaccess + * @return string String containing all rewrite rules to be written in htaccess + * including Media Vault custom rewrite rules + */ +function mgjp_mv_add_plugin_rewrite_rules( $rules ) { + + $pattern = "RewriteRule ^index\.php$ - [L]\n"; + + return str_replace( $pattern, "$pattern\n" . implode( "\n", mgjp_mv_get_the_rewrite_rules() ) . "\n\n", $rules ); +} + + +/** + * Change upload directory for media uploads to a protected + * folder if the 'protected' post/get parameter has been set + * during the upload process. + * + * @since 0.1 + * + * @uses mgjp_mv_upload_dir() + * @param $param array Array of path info for WP Upload Directory + * @return array Array of path info for Media Vault protected directory + */ +function mgjp_mv_change_upload_directory( $param ) { + + if ( isset( $_POST['mgjp_mv_protected'] ) && 'on' == $_POST['mgjp_mv_protected'] ) { + $param['subdir'] = mgjp_mv_upload_dir( $param['subdir'], true ); + $param['path'] = $param['basedir'] . $param['subdir']; + $param['url'] = $param['baseurl'] . $param['subdir']; + } + + return $param; +} + + +/** + * Function for the 'user_has_cap' WP Core filter. Checks the permissions set + * on an attachment before making it available to a user to edit/delete/read. + * + * @since 0.7 + * + * @uses mgjp_mv_check_user_permitted() + * @param $allcaps array Array of all user capabilities + * @param $cap array [0] string capability required + * @param $args array [0] string capability requested + * [1] int user ID + * [2] int post ID + * @return array @param $allcaps unchanged if user permitted to access post + * @return array @param $allcaps with capability @param $cap[0] set to false + */ +function mgjp_mv_edit_capabilities( $allcaps, $cap, $args ) { + + $disallowed_caps = array( + 'edit_post', + 'delete_post', + 'read_post' + ); + + if ( ! in_array( $args[0], $disallowed_caps ) ) + return $allcaps; + + if ( ! isset( $args[2] ) ) + return $allcaps; + + // check if user is permitted to access the post + if ( mgjp_mv_check_user_permitted( $args[2] ) ) + return $allcaps; + + $allcaps[$cap[0]] = false; + + return $allcaps; +} + + +/** + * Replace requested image with a Media Vault place-holder + * if the user is not permitted to view them + * + * @since 0.8 + * + * @param $img mixed false based on wp-includes/media.php or array if other filter has affected it + * @param $attachment_id int ID of the attachment whose image is being requested + * @param $size string name-id of the dimensions of the requested image + * @return mixed return the $url if the image is not protected + * @return array [0] string URL to the Media Vault replacement image of the requested size + * [1] string width of the Media Vault replacement image + * [2] string height of the Media Vault replacement image + * [3] bool whether the url is for a resized image or not + */ +function mgjp_mv_replace_protected_image( $img, $attachment_id, $size ) { + + $ir = get_option( 'mgjp_mv_ir' ); + + if ( ! isset( $ir['is_on'] ) || ! $ir['is_on'] ) + return $img; + + $upload_dir = wp_upload_dir(); + + if ( isset( $img[0] ) && 0 !== strpos( ltrim( $img[0], $upload_dir['baseurl'] ), mgjp_mv_upload_dir( '/', true ) ) ) + return $img; + + if ( mgjp_mv_check_user_permitted( $attachment_id ) ) + return $img; + + if ( isset( $ir['id'] ) && ! mgjp_mv_is_protected( $ir['id'] ) ) { + + remove_filter( 'image_downsize', 'mgjp_mv_replace_protected_image', 999, 3 ); + $placeholder = wp_get_attachment_image_src( $ir['id'], $size ); + add_filter( 'image_downsize', 'mgjp_mv_replace_protected_image', 999, 3 ); + + return $placeholder; + + } else { + + list( $width, $height ) = image_constrain_size_for_editor( 1024, 1024, $size ); + + return array( + plugins_url( 'imgs/media-vault-ir.jpg', __FILE__ ), + $width, + $height, + false + ); + + } +} + + +/** + * Include the Media Vault custom AJAX actions + * + * @since 0.8 + */ +function mgjp_mv_ajax_actions_include() { + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + include( plugin_dir_path( __FILE__ ) . 'mv-ajax-actions.php' ); + +} + + +/** + * Include the plugin's general settings + * + * @since 0.4 + */ +function mgjp_mv_media_vault_options_include() { + + include( plugin_dir_path( __FILE__ ) . 'mv-options-media-vault.php' ); + +} + + +/** + * Include the custom attachment metabox functions + * + * @since 0.7.1 + */ +function mgjp_mv_attachment_metabox_include() { + + include( plugin_dir_path( __FILE__ ) . 'mv-metaboxes.php' ); + +} + + +/** + * Include the options for protected media uploads + * on the 'media-new.php' admin page + * + * @since 0.2 + */ +function mgjp_mv_media_new_options_include() { + + include( plugin_dir_path( __FILE__ ) . 'mv-options-media-new.php' ); + +} + + +/** + * Include the options for protected media uploads + * on the 'upload.php' (Media Library) admin page + * + * @since 0.3 + */ +function mgjp_mv_media_library_options_include() { + + include( plugin_dir_path( __FILE__ ) . 'mv-options-media-library.php' ); + +} + + +/** + * Add Media Vault flag to enable + * Media Vault mp6 styles for WP 3.8+ + * + * @since 0.8.7 + * + * @param $classes string admin body classes + * @return string admin body classes + */ +if ( ! function_exists( 'mgjp_add_mp6_admin_body_class' ) ) { + function mgjp_add_mp6_admin_body_class( $classes ) { + + global $wp_version; + + if ( version_compare( '3.7.5', $wp_version, '>' ) ) + return $classes; + + return $classes . ' mgjp_mp6 '; + } +} + + +/** + * Add Media Vault settings link on plugins manager page + * + * @since 0.8 + * + * @param $links array Array of links associated with plugin + * @return array Array of links associated with plugin plus settings link + */ +function mgjp_mv_settings_link( $links ) { + + $settings_link = '' + . esc_html__( 'Settings', 'media-vault' ) + . ''; + + array_push( $links, $settings_link ); + + return $links; +} + + + +//-----------------------------------------------------------------------// +// MEDIA VAULT - GENERAL FUNCTIONS +//-----------------------------------------------------------------------// + + +/** + * Media Vault internal Activation function for a single + * blog install or for each blog site + * in network activation mode + * + * @since 0.8.5 + * + * @uses mgjp_mv_default_options() + * @uses mgjp_mv_load_placeholder_image() + */ +function _mgjp_mv_activate_local( $blog_id = 0 ) { + + // register Media Vault options to the local options table + add_option( 'mgjp_mv_default_permission', 'logged-in', '', 'yes' ); + + add_option( 'mgjp_mv_options', mgjp_mv_default_options(), '', 'no' ); + add_option( 'mgjp_mv_ir', array( 'is_on' => true ), '', 'no' ); + + mgjp_mv_load_placeholder_image(); + + do_action( 'mgjp_mv_activated_local', $blog_id ); +} + + +/** + * Checks whether Media Vault requires extra + * deactivation steps before it can be correctly + * deactivated + * + * @since 0.8.5 + * + * @return bool true + * false + */ +function mgjp_mv_is_deactivation_allowed() { + + if ( 'temp' === get_site_option( 'mgjp_mv_deactivation' ) ) + return true; + + global $is_apache; + if ( $is_apache + && ! is_multisite() + && get_option( 'permalink_structure' ) + && is_writable( get_home_path() . '.htaccess' ) ) + return true; + + if ( ! mgjp_mv_check_rewrite_rules( true ) ) + return true; + + return false; +} + + +/** + * Media Vault internal Deactivation function for a single + * blog install or for each blog site + * in network activation mode + * + * @since 0.8.5 + */ +function _mgjp_mv_deactivate_local( $blog_id = 0 ) { + + // unload default placeholder image if it exists + $ir = get_option( 'mgjp_mv_ir' ); + if ( isset( $ir['default'] ) && wp_attachment_is_image( $ir['default'] ) ) + wp_delete_attachment( $ir['default'], true ); + + do_action( 'mgjp_mv_deactivated_local', $blog_id ); +} + + +/** + * Return the relative "Path to plugin file with plugin data" + * + * @since 0.8.5 + * + * @return string + */ +function mgjp_mv_get_dirfile() { + + $plugin_dir = explode( '/', plugin_basename( __FILE__ ) ); + $plugin_dir = $plugin_dir[0]; + + $plugin_file = array_keys( get_plugins( "/$plugin_dir" ) ); + $plugin_file = $plugin_file[0]; + + return "$plugin_dir/$plugin_file"; +} + + +/** + * Return the Media Vault protected upload folder + * + * @since 0.1 + * + * @param $path string path to attach to the end of protected folder dirname + * @param $in_url bool set to true if slash before protected folder dirname is desired + * @return string Media Vault protected upload folder relative to WP uploads folder + */ +function mgjp_mv_upload_dir( $path = '', $in_url = false ) { + + $dirpath = $in_url ? '/' : ''; + $dirpath .= '_mediavault'; + $dirpath .= $path; + + return $dirpath; + +} + + +/** + * Generate the rewrite rules to reroute requests for + * media uploads within protected folders and requests + * for media uploads with the `safeforce` download flag + * set, to the file-handling script. Even supporting + * WP Multisite. + * + * @since 0.8.5 + * + * @uses mgjp_mv_upload_dir() + * @return array Array of strings of each line of the + * plugin's custom rewrite rules. + */ +function mgjp_mv_get_the_rewrite_rules() { + + $upload = wp_upload_dir(); + $uploads_path = str_replace( site_url( '/' ), '', $upload['baseurl'] ); + + // if is multisite add allowance for '/sites/ID' folders in uploads path + if ( is_multisite() ) + $uploads_path .= '(?:/sites/[0-9]+)?'; + + // if multisite is on sub-directory mode add allowance for the site's + // sub-directory in the rewrite regex + if ( is_multisite() && ! is_subdomain_install() ) + $uploads_path = '(?:[_0-9a-zA-Z-]+/)?' . $uploads_path; + + $old_path_protected = $uploads_path . '(' . mgjp_mv_upload_dir( '/.*\.\w+)$', true ); + $old_path_downloads = $uploads_path . '(/.*\.\w+)$'; + + $rewrite_rules = array( + '# Media Vault Rewrite Rules', + 'RewriteRule ^' . $old_path_protected . ' index.php?mgjp_mv_file=$1 [QSA,L]', + 'RewriteCond %{QUERY_STRING} ^(?:.*&)?mgjp_mv_download=safeforce(?:&.*)?$', + 'RewriteRule ^' . $old_path_downloads . ' index.php?mgjp_mv_file=$1 [QSA,L]', + '# Media Vault Rewrite Rules End' + ); + + // if pretty permalinks not enabled then produce the code necessary for the user to manually + // add the rules to .htaccess + if ( ! is_multisite() && ! get_option( 'permalink_structure' ) ) { + $home_root = parse_url( home_url() ); + if ( isset( $home_root['path'] ) ) + $home_root = trailingslashit( $home_root['path'] ); + else + $home_root = '/'; + + array_splice( $rewrite_rules, 1, 0, array( + '', + 'RewriteEngine On', + 'RewriteBase ' . $home_root + ) ); + array_splice( $rewrite_rules, -1, 0, array( + '' + ) ); + } + + return apply_filters( 'mgjp_mv_get_rewrite_rules', $rewrite_rules ); + +} + +/** + * Check if request rewrite rules have been configured correctly + * Don't call on every init! - it makes **at least** two http + * requests every time it is called! + * + * @since 0.8.5 + * + * @uses mgjp_mv_upload_dir() + * @return bool + */ +function mgjp_mv_check_rewrite_rules( $deactivation = false ) { + + $upload_dir = wp_upload_dir(); + + $protected_test = mgjp_mv_upload_dir( '/mgjp_mv_rewrite_test.txt?mgjp_mv_rewrite_test=1', true ); + $downloads_test = '/mgjp_mv_rewrite_test.txt?mgjp_mv_download=safeforce&mgjp_mv_rewrite_test=1'; + + $checks = array( + $upload_dir['baseurl'] . $protected_test, + $upload_dir['baseurl'] . $downloads_test + ); + + $checks = apply_filters( 'mgjp_mv_rewrite_rule_check_urls', $checks ); + + $checks_passed = true; + foreach ( $checks as $check_url ) { + + $check = wp_remote_get( $check_url ); + + if ( is_wp_error( $check ) + || ! isset( $check['response']['code'] ) || 200 != $check['response']['code'] + || ! isset( $check['body'] ) || 'pass' != $check['body'] ) + $checks_passed = false; + else + $checks_passed = true; + + if ( ( ! $deactivation && ! $checks_passed ) || ( $deactivation && $checks_passed ) ) + break; + } + + return $checks_passed; + +} + + +/** + * Adds the default Media Vault place-holder image to the + * Media Library and saves the id of the attachment created + * in the 'mgjp_mv_ir' option in the options table + * + * @since 0.8 + * + * @return int the ID of the attachment that was created + * @return bool true on success + * @return bool false on failure to load image + */ +function mgjp_mv_load_placeholder_image( $restore_orig = false ) { + + $ir = get_option( 'mgjp_mv_ir' ); + + // if placeholder image already exists return its attachment ID + if ( isset( $ir['id'] ) && wp_attachment_is_image( $ir['id'] ) && ! $restore_orig ) + return $ir['id']; + + // if original placeholder is loaded no need to + // reload it. Set it as placeholder and return its ID + if ( isset( $ir['default'] ) && wp_attachment_is_image( $ir['default'] ) ) { + $ir['id'] = $ir['default']; + update_option( 'mgjp_mv_ir', $ir ); + return $ir['id']; + } + + require_once( ABSPATH . 'wp-admin/includes/file.php' ); + require_once( ABSPATH . 'wp-admin/includes/media.php' ); + require_once( ABSPATH . 'wp-admin/includes/image.php' ); + + $tmp = download_url( plugins_url( 'imgs/media-vault-ir.jpg', __FILE__ ) ); + + if ( is_wp_error( $tmp ) ) { + @ unlink( $tmp ); + return false; + } + + $file_array = array( + 'name' => 'media-vault-ir.jpg', + 'tmp_name' => $tmp + ); + + $post_data['post_date_gmt'] = $post_data['post_date'] = '1988-01-31 12:00:00'; + + $id = media_handle_sideload( + $file_array, + 0, + __( 'Do Not Delete, Media Vault Place-holder Image' , 'media-vault' ), + $post_data + ); + + if ( is_wp_error( $id ) ) { + @ unlink( $tmp ); + return false; + } + + $ir['default'] = $id; + $ir['id'] = $id; + + update_option( 'mgjp_mv_ir', $ir ); + + return $id; +} + + +/** + * Check if an attachment is protected with Media Vault. + * + * A file is protected by media vault if and only if + * it is in the Media Vault Protected Directory within + * the WordPress Uploads Directory. + * ( eg: wp-content/uploads/_mediavault/../filename.ext ) + * + * If a file is in the protected directory and no permission + * meta is detected for the file, the default permission is + * used to check if the user is allowed access. + * + * So to check if an attachment is protected by Media Vault we + * need to check whether its files are within the Media Vault + * Protected Directory. + * + * @since 0.8 + * + * @uses mgjp_mv_upload_dir() + * @param $attachment_id int the id of the attachment we want to check + */ +function mgjp_mv_is_protected( $attachment_id ) { + + // Get the base file path relative to the WordPress Uploads Directory + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); + + // Check if the path begins with the Media Vault Protected Directory + // Therefore check if the attachment's files are in the protected directory + if ( 0 === stripos( $file, mgjp_mv_upload_dir( '/' ) ) ) + return true; + + return false; +} + + + + + +/** + * Adds a permission to the Media Vault permissions array + * + * @since 0.6 + * + * @uses $mgjp_mv_permissions + * @param $name string Name-id of the new permission, must be unique + * @param $args array Array of arguments for permission must include: + * [description] string Human readable short description of permission + * [select] string Human readable very consice description of permission, used in option of select element + * [logged_in] bool Whether the user must be at least logged in + * [run_in_admin] bool Whether to run the permission check in WP Admin + * [cb] string Function name to be called to evaluate file access permissions, false if no callback desired + * Function MUST return TRUE if access permitted to file and FALSE or WP_Error if access denied + * @return bool false on failure, true on success + */ +function mgjp_mv_add_permission( $name, $args ) { + + $allowed_keys = array( 'description', 'select', 'logged_in', 'run_in_admin', 'cb' ); + + $safe_args = array(); + foreach ( $allowed_keys as $key ) { + if ( isset( $args[$key] ) ) + $safe_args[$key] = $args[$key]; + } + + if ( count( $allowed_keys ) !== count( $safe_args ) ) + return false; + + global $mgjp_mv_permissions; + if ( isset( $mgjp_mv_permissions[$name] ) ) + return false; + + $mgjp_mv_permissions[$name] = $safe_args; + + return true; +} + +/** + * Returns the array of permission array objects + * + * @since 0.4 + * + * @uses apply_filters() to provide hook to change default permissions, or + * add / remove custom permission objects + * @uses $mgjp_mv_permissions + * @return array Array of Media Vault file access permissions + */ +function mgjp_mv_get_the_permissions() { + + global $mgjp_mv_permissions; + + return apply_filters( 'mgjp_mv_edit_permissions', $mgjp_mv_permissions ); +} + +/** + * Returns the Media Vault file access permission for an attachment + * or false if the attachment's files are not marked as protected + * + * @since 0.7 + * + * @uses mgjp_mv_is_protected() + * @return bool false if attachment is not protected + * @return string the permission name-id set for this attachment if it is protected + */ +function mgjp_mv_get_the_permission( $attachment_id, $meta_only = false ) { + + if ( ! mgjp_mv_is_protected( $attachment_id ) ) + return false; + + $permission = get_post_meta( $attachment_id, '_mgjp_mv_permission', true ); + + return empty( $permission ) && ! $meta_only ? + get_option( 'mgjp_mv_default_permission', 'logged-in' ) : + $permission; +} + +/** + * Check if the current user is permitted to access an attachment of a + * specified ID + * + * @since 0.7 + * + * @uses mgjp_mv_get_the_permission() + * @uses mgjp_mv_get_the_permissions() + * @param $attachment_id int The id of the attachment to check against + * @return bool True if current user access permitted + * @return bool False if current user access denied + */ +function mgjp_mv_check_user_permitted( $attachment_id ) { + + // check if attachment has protection and permissions set on it + if ( ! $permission = mgjp_mv_get_the_permission( $attachment_id ) ) + return true; + + $permissions = mgjp_mv_get_the_permissions(); + + // check if permission set on attachment is valid + if ( ! isset( $permissions[$permission] ) ) + return false; // it is better to fail safely than to reveal something we should not + + // check if permission check is set to need not run in admin + if ( is_admin() && isset( $permissions[$permission]['run_in_admin'] ) && ! $permissions[$permission]['run_in_admin'] ) + return true; + + // check if permission check is set to need the user to be logged in. if it is check if he is logged in + if ( ! isset( $permissions[$permission]['logged_in'] ) || ( $permissions[$permission]['logged_in'] && ! is_user_logged_in() ) ) + return false; + + // check if permission callback is set to false + if ( isset( $permissions[$permission]['cb'] ) && false === $permissions[$permission]['cb'] ) + return true; + + // if not false (above), check if permission callback is valid, fail safely if it is not + if ( ! is_callable( $permissions[$permission]['cb'] ) ) + return false; + + // perform the defined permission check callback on the user for this attachment + // function MUST return true if the user is allowed access + $permission_check = call_user_func( $permissions[$permission]['cb'], $attachment_id ); + + // if there are no errors permit access + if ( true === $permission_check ) + return true; + + return false; +} + + +/** + * Moves attachment files to Media Vault protected + * directory in the WP uploads folder + * + * @since 0.8 + * + * @uses mgjp_move_attachment_files() + * @param $attachment_id int the id of the attachment whose files we want to move + * @return object WP_Error with error txt from mgjp_move_attachment_files() on failure + * @return bool true on success + */ +function mgjp_mv_move_attachment_to_protected( $attachment_id ) { + + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); + + // check if files are already in the Media Vault protected folder + if ( 0 === stripos( $file, mgjp_mv_upload_dir( '/' ) ) ) + return true; + + $reldir = dirname( $file ); + if ( in_array( $reldir, array( '\\', '/', '.' ), true ) ) + $reldir = ''; + + $new_reldir = path_join( mgjp_mv_upload_dir(), $reldir ); + + require_once( plugin_dir_path( __FILE__ ) . 'includes/mgjp-functions.php' ); + + return mgjp_move_attachment_files( $attachment_id, $new_reldir ); +} + +/** + * Moves attachment files out of Media Vault protected + * directory in the WP uploads folder + * + * @since 0.8 + * + * @uses mgjp_move_attachment_files() + * @param $attachment_id int the id of the attachment whose files we want to move + * @return object WP_Error with error txt from mgjp_mv_move_attachment_files() on failure + * @return bool true on move success + */ +function mgjp_mv_move_attachment_from_protected( $attachment_id ) { + + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); + + // check if files are already not in the Media Vault protected folder + if ( 0 !== stripos( $file, mgjp_mv_upload_dir( '/' ) ) ) + return true; + + $new_reldir = ltrim( dirname( $file ), mgjp_mv_upload_dir( '/' ) ); + + require_once( plugin_dir_path( __FILE__ ) . 'includes/mgjp-functions.php' ); + + return mgjp_move_attachment_files( $attachment_id, $new_reldir ); +} + + +/** + * Return attachment file download url + * + * @since 0.5 + * + * @param $attachment_id int ID of attachment whose file download url we want + * @param $size string optional name-id of size of file if attachment is of type 'image' + * @return object WP_Error with error txt if file is not attachment + * @return string full filepath to attachment file of specified size with Media Vault force download + * query parameter set + */ +function mgjp_mv_get_attachment_download_url( $attachment_id, $size = null ) { + + if ( 'attachment' !== get_post_type( $attachment_id ) ) + return new WP_Error( 'not_attachment', sprintf( __( 'The post type of the post with ID %d, is not %s.', 'media-vault' ), $attachment_id, '\'attachment\'' ) ); + + $query_arg = array( 'mgjp_mv_download' => 'safeforce' ); + + if ( ! wp_attachment_is_image( $attachment_id ) || ! isset( $size ) ) + return add_query_arg( $query_arg, wp_get_attachment_url( $attachment_id ) ); + + $image = wp_get_attachment_image_src( $attachment_id, $size ); + + return add_query_arg( $query_arg, $image[0] ); +} + + +/** + * Return plugin default options + * + * @since 0.4 + * + * @uses apply_filters() provides hook to modify default plugin options + * @return array Array of Media Vault options + */ +function mgjp_mv_default_options() { + + $options = array( + 'default_upload_protection' => 'off' // possible values 'on' && 'off' + ); + + return apply_filters( 'mgjp_mv_default_options', $options ); + +} + + +/** + * Echo Media Vault Custom + * admin notice + * + * @since 0.8.5 + * + * @param $desc string Notice text, can contain 'em' & 'strong' html tags + * @param $link array (optional) [link] link + * [text] link text + */ +function mgjp_mv_admin_notice( $desc, $links = null ) { + + wp_enqueue_style( 'mgjp-mv-admin-notice', plugins_url( 'css/mv-admin-notice.css', __FILE__ ), 'all', null ); + + ?> + +
+
+ + + + +
+ + + + + + + + + + +
+ + +
+
+
+ array(), 'strong' => array() ), false ); ?> +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/css/mv-admin-notice.css b/css/mv-admin-notice.css new file mode 100644 index 0000000..03c59e8 --- /dev/null +++ b/css/mv-admin-notice.css @@ -0,0 +1 @@ +.mgjp-mv-admin-notice{margin:15px 0;border:1px solid #124e32;border-radius:3px;height:60px;background:#2bb673;background:-webkit-linear-gradient(left,#2bb673,#124e32);background:-webkit-gradient(linear,top left,top right,from(#2bb673),to(#124e32));background:-webkit-linear-gradient(left,#2bb673,#124e32);background:linear-gradient(to right,#2bb673,#124e32);overflow:hidden;*zoom:1}.mgjp-mv-admin-notice:after,.mgjp-mv-admin-notice:before{content:' ';display:table}.mgjp-mv-admin-notice:after{clear:both}.mgjp-mv-admin-notice-logo{position:relative;float:right}.mgjp-mv-admin-notice-logo:after{content:'';position:absolute;top:0;right:0;height:0;width:70px;border-left:40px solid transparent;border-bottom:60px solid #fafafa}.mgjp-mv-admin-notice-logo img{position:relative;margin:5px 10px;height:50px;z-index:1}.mgjp-mv-admin-notice-btn-box{position:relative;float:left;margin-left:10px;padding:0 55px;height:60px;text-align:center;line-height:60px}.mgjp-mv-admin-notice-btn-box:after,.mgjp-mv-admin-notice-btn-box:before{content:'';position:absolute;top:0;height:0;width:50%}.mgjp-mv-admin-notice-btn-box:before{left:0;border-left:40px solid transparent;border-bottom:60px solid #2a2b2a}.mgjp-mv-admin-notice-btn-box:after{right:0;border-top:60px solid #2a2b2a;border-right:40px solid transparent}.mgjp-mv-admin-notice-button{position:relative;display:inline-block;border:1px solid #029DD6;border-top-color:#06B9FD;border-radius:3px;padding:10px 20px!important;font-size:15px;font-weight:700;line-height:1.4em;color:#FFF;background:#029DD6;background:-webkit-linear-gradient(top,#029dd6,#0079b1);background:-webkit-gradient(linear,top left,bottom left,from(#029dd6),to(#0079b1));background:-webkit-linear-gradient(top,#029dd6,#0079b1);background:linear-gradient(to bottom,#029dd6,#0079b1);z-index:1}.mgjp-mv-admin-notice-button+.mgjp-mv-admin-notice-button{margin-left:5px}.mgjp-mv-admin-notice-button:focus,.mgjp-mv-admin-notice-button:hover{border:1px solid #029DD6;border-bottom-color:#00A8EF;text-decoration:none!important;color:#F0F8FB;background:#0079B1;background:-webkit-linear-gradient(top,#0079b1,#0092bf);background:-webkit-gradient(linear,top left,bottom left,from(#0079b1),to(#0092bf));background:-webkit-linear-gradient(top,#0079b1,#0092bf);background:linear-gradient(to bottom,#0079b1,#0092bf)}.mgjp-mv-valign-outer{display:table;height:100%}.mgjp-mv-valign-mid{display:table-cell;vertical-align:middle}.mgjp-mv-valign-inner{display:table}.mgjp-mv-admin-notice-desc{margin-left:15px;margin-right:45px;color:#fff;color:rgba(255,255,255,.8);font-size:15px}.mgjp-mv-admin-notice-desc strong{color:#fff} \ No newline at end of file diff --git a/css/mv-attachment-edit.css b/css/mv-attachment-edit.css new file mode 100644 index 0000000..756efcc --- /dev/null +++ b/css/mv-attachment-edit.css @@ -0,0 +1 @@ +#mgjp_mv_protection_toggle,.js .js-visuallyhidden,.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}#mgjp_mv_protection_metabox .inside{position:static}#mgjp_mv_protection_metabox p.mgjp-mv-permission-select{margin:0 0 3.5em!important;max-height:0;opacity:0;overflow:hidden;-webkit-transition:.5s opacity, .5s .1s max-height;transition:.5s opacity, .5s .1s max-height}.mgjp-mv-protection-toggle{position:absolute;left:0;right:0;bottom:0;padding:1em 15px}.mgjp-mv-protection-toggle .mgjp-on{width:100%;text-align:center}.mgjp-mv-protection-toggle .mgjp-off{display:none;color:red}.mgjp-mv-protection-toggle .mgjp-off:after,.mgjp-mv-protection-toggle .mgjp-on:after{content:attr(data-mgjp-content);speak:none}#mgjp_mv_protection_toggle:checked~p.mgjp-mv-permission-select,p.mgjp-mv-permission-select.mgjp-mv-active{margin-bottom:4.2em!important;max-height:100px;opacity:1;-webkit-transition:.3s .1s opacity, .5s max-height ease-out;transition:.3s .1s opacity, .5s max-height ease-out}#mgjp_mv_protection_toggle:checked+.mgjp-mv-protection-toggle{border-top:1px solid #dfdfdf;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff}#mgjp_mv_protection_toggle:checked+.mgjp-mv-protection-toggle .mgjp-on{display:none}#mgjp_mv_protection_toggle:checked+.mgjp-mv-protection-toggle .mgjp-off{display:block}.mgjp_mp6 #mgjp_mv_protection_metabox p.mgjp-mv-permission-select,.mp6 #mgjp_mv_protection_metabox p.mgjp-mv-permission-select{margin-bottom:2.7em!important}.mgjp_mp6 .mgjp-mv-protection-toggle .mgjp-off,.mp6 .mgjp-mv-protection-toggle .mgjp-off{color:#a00;border-bottom:0}.mgjp_mp6 .mgjp-mv-protection-toggle .mgjp-off:active,.mgjp_mp6 .mgjp-mv-protection-toggle .mgjp-off:focus,.mgjp_mp6 .mgjp-mv-protection-toggle .mgjp-off:hover,.mp6 .mgjp-mv-protection-toggle .mgjp-off:active,.mp6 .mgjp-mv-protection-toggle .mgjp-off:focus,.mp6 .mgjp-mv-protection-toggle .mgjp-off:hover{color:red}.mgjp_mp6 #mgjp_mv_protection_toggle:checked~p.mgjp-mv-permission-select,.mgjp_mp6 p.mgjp-mv-permission-select.mgjp-mv-active,.mp6 #mgjp_mv_protection_toggle:checked~p.mgjp-mv-permission-select,.mp6 p.mgjp-mv-permission-select.mgjp-mv-active{margin-bottom:2.4em!important}.mgjp_mp6 #mgjp_mv_protection_toggle:checked+.mgjp-mv-protection-toggle,.mp6 #mgjp_mv_protection_toggle:checked+.mgjp-mv-protection-toggle{border-top:0;-webkit-box-shadow:none;box-shadow:none} \ No newline at end of file diff --git a/css/mv-attachment-fields.css b/css/mv-attachment-fields.css new file mode 100644 index 0000000..cb6f0c7 --- /dev/null +++ b/css/mv-attachment-fields.css @@ -0,0 +1 @@ +.compat-attachment-fields .mgjp_mv_attachment_fields{border-bottom:1px solid #fbfbfb;-webkit-box-shadow:inset 0 -1px 0 0 #ddd;box-shadow:inset 0 -1px 0 0 #ddd}.compat-attachment-fields .mgjp_mv_attachment_fields label.button{width:100%;white-space:normal}@media only screen and (min-width:901px){.compat-attachment-fields .mgjp_mv_attachment_fields th{padding-top:0;width:35%;text-align:right;vertical-align:top;font-weight:400}.compat-attachment-fields .mgjp_mv_attachment_fields p{padding-left:15px}}@media only screen and (max-width:900px){.compat-attachment-fields .mgjp_mv_attachment_fields select,.compat-attachment-fields .mgjp_mv_attachment_fields td,.compat-attachment-fields .mgjp_mv_attachment_fields th{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;display:block;width:100%}} \ No newline at end of file diff --git a/css/mv-eas-page.css b/css/mv-eas-page.css new file mode 100644 index 0000000..e83ca28 --- /dev/null +++ b/css/mv-eas-page.css @@ -0,0 +1 @@ +.mgjp-mv-icon{height:50px;vertical-align:middle}p{max-width:920px;line-height:1.7em} \ No newline at end of file diff --git a/css/mv-media-new.css b/css/mv-media-new.css new file mode 100644 index 0000000..55f5c8e --- /dev/null +++ b/css/mv-media-new.css @@ -0,0 +1 @@ +.js .js-visuallyhidden,.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}#plupload-upload-ui{position:relative}#plupload-upload-ui .mgjp-mv-tag{display:none;position:absolute;top:25px;left:50%;margin-left:-102px;border:1px solid #b4b4b4;border-radius:5px;padding:8px 15px;color:#333;background:#e6e6e6;background-image:-webkit-linear-gradient(top,#e6e6e6 7%,#d8d8d8 77%);background-image:-webkit-gradient(linear,top left,bottom left,from(#e6e6e6),to(#d8d8d8));background-image:-webkit-linear-gradient(top,#e6e6e6 7%,#d8d8d8 77%);background-image:linear-gradient(to bottom,#e6e6e6 7%,#d8d8d8 77%)}#plupload-upload-ui .mgjp-mv-tag .mgjp-mv-tag-icon{float:left;background:center no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAhxJREFUeNqkU89rE0EYfTOZbDdmk5qo1EZ6qKDYXgRl9SLGUiNI/wQPxYsgFPQkXvXgXaQXD4qCIF4UPAiCtaGiSFTQgwpRA1pjY4yx2cRN9kfGb2pWm1gx4MCDmbf7vXnz5hsmpcT/DHb7NO8iQpxB17CbAWlaDnXoEm2TbTp46re7NxS9imTIFEbq2NjE0UPFpS8RxaU2b7Rf3b88JivFi7TMdQnYzh8SmV37pqce3btbffn88S3FjO/ce9DcPz21cONcoVeAa4IhgGVDYUQyfeh9/tmiJnBCQc0Vp76pf0SIIdyBWB/t7KsCYQyFUttoLNc4pNsy6ACVGqCF3ZZt1bllSyOVZIgRT1H9DHH+TCgQOO562P7kjT+8LcXrFUsmRAjep69ydNMg+9BuI/KtIWvjI9yK6uwFCVzoDXFrZubqyQPfbTjNJhyb0LJRreQxoMFcpwMKEUNg/vqV82veQi6bheAcQgg6Dofve6hWbYTIpB6mYg2IxsJ/v0YznYbb42BAqysHWO3g7cNVAnTuIAPZrwOqkUGIYrH0q7P8zEx/DubK0mWBg7M3JY7sWZlr/ToofJRhJXCNWkoUyhKXHjAc3oEN5uQkfMeFRw48cuCRg3jcg0aFuv4bSxUk7rwGissSSiip2n1iFKeG40iQzXJykDWSCXAjithCTm7p9BkC258byM+9wyxNi4pTDya21sP6x1DxWz8EGACn4vFm357hkgAAAABJRU5ErkJggg==);-webkit-background-size:cover;background-size:cover;margin-right:5px;width:14px;height:14px}.mgjp_mp6 #plupload-upload-ui .mgjp-mv-tag,.mp6 #plupload-upload-ui .mgjp-mv-tag{margin-left:-108px;border:0;border-radius:0;padding:10px 20px 10px 15px;color:#eee;background:#333}.mgjp_mp6 #plupload-upload-ui .mgjp-mv-tag .mgjp-mv-tag-icon,.mp6 #plupload-upload-ui .mgjp-mv-tag .mgjp-mv-tag-icon{background:0 0;height:auto;width:auto}.mgjp_mp6 #plupload-upload-ui .mgjp-mv-tag .mgjp-mv-tag-icon:before,.mp6 #plupload-upload-ui .mgjp-mv-tag .mgjp-mv-tag-icon:before{content:'\f160';font:400 18px/1 dashicons!important;speak:none;color:#999;height:20px;width:20px;vertical-align:top;-webkit-font-smoothing:antialiased}#plupload-upload-ui.mgjp-mv-checked #drag-drop-area{-webkit-transition:border .1s;-webkit-transition-delay:1.75s;transition:border .1s 1.75s;border-color:#21759b}#plupload-upload-ui.mgjp-mv-checked .mgjp-mv-tag{display:block;-webkit-animation:appear-and-land 2s;animation:appear-and-land 2s}#plupload-upload-ui.mgjp-mv-unchecked #drag-drop-area{-webkit-transition:border .7s;transition:border .7s}#plupload-upload-ui.mgjp-mv-unchecked .mgjp-mv-tag{display:block;opacity:0;-webkit-transition:opacity .7s;transition:opacity .7s}@-webkit-keyframes appear-and-land{from{opacity:0;-ms-transform:translateY(70px) scale(1.1);-webkit-transform:translateY(70px) scale(1.1);transform:translateY(70px) scale(1.1);-webkit-box-shadow:0 15px 10px -10px rgba(0,0,0,.3);box-shadow:0 15px 10px -10px rgba(0,0,0,.3)}50%{opacity:1;-ms-transform:scale(1.1);-webkit-transform:scale(1.1);transform:scale(1.1);-webkit-box-shadow:0 15px 10px -10px rgba(0,0,0,.3);box-shadow:0 15px 10px -10px rgba(0,0,0,.3)}85%{-ms-transform:translateY(-10px) scale(1.3);-webkit-transform:translateY(-10px) scale(1.3);transform:translateY(-10px) scale(1.3);-webkit-box-shadow:0 27px 15px -18px rgba(0,0,0,.5);box-shadow:0 27px 15px -18px rgba(0,0,0,.5)}87%{-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);-webkit-box-shadow:0 0 #000;box-shadow:0 0 #000}to{-webkit-box-shadow:0 0 90px transparent;box-shadow:0 0 90px transparent}}@keyframes appear-and-land{from{opacity:0;-ms-transform:translateY(70px) scale(1.1);-webkit-transform:translateY(70px) scale(1.1);transform:translateY(70px) scale(1.1);-webkit-box-shadow:0 15px 10px -10px rgba(0,0,0,.3);box-shadow:0 15px 10px -10px rgba(0,0,0,.3)}50%{opacity:1;-ms-transform:scale(1.1);-webkit-transform:scale(1.1);transform:scale(1.1);-webkit-box-shadow:0 15px 10px -10px rgba(0,0,0,.3);box-shadow:0 15px 10px -10px rgba(0,0,0,.3)}85%{-ms-transform:translateY(-10px) scale(1.3);-webkit-transform:translateY(-10px) scale(1.3);transform:translateY(-10px) scale(1.3);-webkit-box-shadow:0 27px 15px -18px rgba(0,0,0,.5);box-shadow:0 27px 15px -18px rgba(0,0,0,.5)}87%{-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);-webkit-box-shadow:0 0 #000;box-shadow:0 0 #000}to{-webkit-box-shadow:0 0 90px transparent;box-shadow:0 0 90px transparent}} \ No newline at end of file diff --git a/imgs/media-vault-ir.jpg b/imgs/media-vault-ir.jpg new file mode 100644 index 0000000..3d97784 Binary files /dev/null and b/imgs/media-vault-ir.jpg differ diff --git a/imgs/media-vault-logo.png b/imgs/media-vault-logo.png new file mode 100644 index 0000000..ce4039f Binary files /dev/null and b/imgs/media-vault-logo.png differ diff --git a/includes/mgjp-functions.php b/includes/mgjp-functions.php new file mode 100644 index 0000000..2d4555a --- /dev/null +++ b/includes/mgjp-functions.php @@ -0,0 +1,292 @@ + + * @license GPL-3.0+ + */ + + +/** + * !WIP: NOT FOR USE: convert a path to be relative to the wp uploads dir if + * possible, otherwise return false. similar to _wp_relative_upload_path() + * + * @since 1.0 + * + * @param $path string Path to check against WP upload dir + * @returns string on success $path converted to relative of WP upload dir + * @returns bool on failure if such conversion is impossible + */ +if ( ! function_exists( 'mgjp_wp_relative_upload_path' ) ) { + function mgjp_wp_relative_upload_path( $path ) { + $path = ltrim( $path, '/' ); + + if ( ! path_is_absolute( $path ) ) + return $path; + + $upload_dir = wp_upload_dir(); + + if ( 0 === strpos( $path, $upload_dir['basedir'] ) ) + $path = str_replace( $upload_dir['basedir'], '', $path ); + + else if ( 0 === strpos( $path, $upload_dir['baseurl'] ) ) + $path = str_replace( $upload_dir['baseurl'], '', $path ); + + else $path = false; + + if ( $path ) + $path = ltrim( $path, '/' ); + + return $path; + } +} + + +/** + * move an attachment's files to another folder within + * the WordPress uploads directory + * + * @since 1.0 + * + * @param $attachment_id int the ID of the attachment whose files we want to move + * @param $new_reldir string the new path to the attachment relative to the WP uploads directory + * @return object | bool Returns WP_Error on failure and True on success + */ +if ( ! function_exists( 'mgjp_move_attachment_files' ) ) { + function mgjp_move_attachment_files( $attachment_id, $new_reldir ) { + + // basic sanity checks + if ( 'attachment' != get_post_type( $attachment_id ) ) + return new WP_Error( 'not_attachment', sprintf( + __( 'The post with ID: %d is not an attachment post type.', 'media-vault' ), + $attachment_id + ) ); + + if ( path_is_absolute( $new_reldir ) ) + return new WP_Error( 'new_reldir_not_relative', sprintf( + __( 'The new path provided: %s is absolute. The new path must be a path relative to the WP uploads directory.', 'media-vault' ), + $new_relpath + ) ); + + + // Get all file related attachment meta data + $meta = wp_get_attachment_metadata( $attachment_id ); // meta_key => '_wp_attachment_metadata' + + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); // meta_key => '_wp_attached_file' + + $backups = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true ); // meta_key => '_wp_attachment_backup_sizes' + + + // Determine the full paths to the directory where the file + // currently is and to the directory we want to put the file in. + $upload_dir = wp_upload_dir(); + + $old_reldir = dirname( $file ); + if ( in_array( $old_reldir, array( '\\', '/', '.' ), true ) ) + $old_reldir = ''; + + // If the files are already in the new directory, we don't need + // to do anything further. + if ( $new_reldir === $old_reldir ) + return 'sfdfdsfsdd'; + + $old_fulldir = path_join( $upload_dir['basedir'], $old_reldir ); + $new_fulldir = path_join( $upload_dir['basedir'], $new_reldir ); + + + // Make sure the directory we want to put the files into exists + // otherwise create it, while setting appropriate permissions. + if ( ! wp_mkdir_p( $new_fulldir ) ) + return new WP_Error( 'wp_mkdir_p_error', sprintf( + __( 'There was an error making or verifying the directory at: %s', 'media-vault' ), + $new_fulldir + ) ); + + + // Get all filenames for all attached files + $intermediate_sizes = array(); + if ( is_array( $meta['sizes'] ) ) { + foreach ( $meta['sizes'] as $size ) { + $intermediate_sizes[] = $size['file']; + } + } + + $backup_sizes = array(); + if ( is_array( $backups ) ) { + foreach ( $backups as $size ) { + $backup_sizes[] = $size['file']; + } + } + + $old_basenames = $new_basenames = array_merge( + array( basename( $file ) ), + $intermediate_sizes, + $backup_sizes + ); + + + // Determine the original filename, to be used to update the guid + // and if we need to change the filenames because there is already + // a file with the same name in the destination directory + $orig_basename = basename( $file ); + if ( is_array( $backups ) && isset( $backups['full-orig'] ) ) + $orig_basename = $backups['full-orig']['file']; + + + // Make sure we are not overwriting any existing files in the + // destination folder. Add numerical increment to filename until + // there are no conflicts. + + // prep for filename conflict script + $orig_filename = pathinfo( $orig_basename ); + $orig_filename = $orig_filename['filename']; + $conflict = true; + $number = 1; + $separator = '#'; + $med_filename = $orig_filename; + + while ( $conflict ) { + + $conflict = false; + foreach ( $new_basenames as $basename ) { + if ( is_file( path_join( $new_fulldir, $basename ) ) ) { + $conflict = true; + break; + } + } + + // filename conflict script + if ( $conflict ) { + $new_filename = "$orig_filename$number"; + $number++; + $pattern = "$separator$med_filename"; + $replace = "$separator$new_filename"; + $new_basenames = explode( + $separator, + ltrim( + str_replace( $pattern, $replace, $separator . implode( $separator, $new_basenames ) ), + $separator + ) + ); + $med_filename = $new_filename; + } + } + + + // php rename() all filepaths in old directory to new path + + // remove duplicate basenames to prevent uneccessary renames + // from happening + $unique_old_basenames = array_values( array_unique( $old_basenames ) ); + $unique_new_basenames = array_values( array_unique( $new_basenames ) ); + + $i = count( $unique_old_basenames ); + while ( $i-- ) { + + $old_fullpath = path_join( $old_fulldir, $unique_old_basenames[$i] ); + $new_fullpath = path_join( $new_fulldir, $unique_new_basenames[$i] ); + + rename( $old_fullpath, $new_fullpath ); + + if ( ! is_file( $new_fullpath ) ) + return new WP_Error( + 'rename_failed', + sprintf( + __( 'Rename failed when trying to move file from: %s, to: %s', 'media-vault' ), + $old_fullpath, + $new_fullpath + ) + ); + } + + + // Update all attachment filepaths in database to point to the new location + + // $new_basenames[0] should always be the basename of the file + // from '_wp_attached_media' with the new conflict free filename + $meta['file'] = path_join( $new_reldir, $new_basenames[0] ); + update_post_meta( $attachment_id, '_wp_attached_file', $meta['file'] ); + + // if $new_basenames != $old_basenames we must update the + // original basename used in the guid as well as the metadata + // of the intermediate and backup sizes to reflect the + // filename changes + if ( $new_basenames[0] != $old_basenames[0] ) { + + // if $new_basenames != $old_basenames that means the + // filename conflict script has run and therefore + // $pattern & $replace are defined + $orig_basename = ltrim ( + str_replace( $pattern, $replace, $separator . $orig_basename ), + $separator + ); + + if ( is_array( $meta['sizes'] ) ) { + $i = 0; + + foreach ( $meta['sizes'] as $size => $data ) { + $meta['sizes'][$size]['file'] = $new_basenames[++$i]; + } + } + + if ( is_array( $backups ) ) { + $i = 0; + $l = count( $backups ); + $new_backup_sizes = array_slice( $new_basenames, -$l, $l ); + + foreach ( $backups as $size => $data ) { + $backups[$size]['file'] = $new_backup_sizes[$i++]; + } + update_post_meta( $attachment_id, '_wp_attachment_backup_sizes', $backups ); + } + + } + + update_post_meta( $attachment_id, '_wp_attachment_metadata', $meta ); + + $guid = path_join( $new_fulldir, $orig_basename ); // should I be updating the GUID? the Codex says I should + // just in case someone wants to disable updating the guid: // for attachments. + if ( apply_filters( 'mgjp_update_guid_on_attachment_files_move', true ) ) + wp_update_post( array( 'ID' => $attachment_id, 'guid' => $guid ) ); + + + // NOT IMPLEMENTED YET: If $rewrite_whole_db flag is set, sanely search through database for instances of + // old filepath and replace them with new filepath + // database tables to look through: -> ? + + + return true; + } +} + +function wpst_mv_register_custom_permissions() { + + if ( function_exists( 'mgjp_mv_add_permission' ) ) { + + mgjp_mv_add_permission( 'contributor-plus', array( + 'description' => 'Contributors and Above', + 'select' => 'Contributors Plus', + 'logged_in' => true, // whether the user must be logged in + 'run_in_admin' => true, // whether to run the access check in admin + 'cb' => 'wpst_mv_restrict_only_for_subscribers' + ) ); + + } + +} +add_action( 'after_setup_theme', 'wpst_mv_register_custom_permissions' ); + +function wpst_mv_restrict_only_for_subscribers() { + + if ( current_user_can( 'edit_posts' ) ) + return true; + + return false; +} + +?> \ No newline at end of file diff --git a/js/min/mv-attachment-edit-ltIE9.min.js b/js/min/mv-attachment-edit-ltIE9.min.js new file mode 100644 index 0000000..6f78d56 --- /dev/null +++ b/js/min/mv-attachment-edit-ltIE9.min.js @@ -0,0 +1 @@ +jQuery(function(e){var c=e(".mgjp-mv-permission-select");e("#mgjp_mv_protection_toggle").change(function(){this.checked?c.addClass("mgjp-mv-active"):c.removeClass("mgjp-mv-active")}).change()}(jQuery)); \ No newline at end of file diff --git a/js/min/mv-attachment-fields.min.js b/js/min/mv-attachment-fields.min.js new file mode 100644 index 0000000..a8bd953 --- /dev/null +++ b/js/min/mv-attachment-fields.min.js @@ -0,0 +1 @@ +!function(e){var t,i,n={};e("body").on("mgjpMvLoaded","#mgjp_mv_attachment_fields",function(o,s){t=s,i=e("#mgjp_mv_attachment_permissions_field"),n.hasOwnProperty(t)&&e(this).find(".mgjp_mv_protection_toggle, .mgjp_mv_permission_select").each(function(){n[t].hasOwnProperty(this.name)&&("checkbox"===this.type?this.checked=n[t][this.name]:this.value=n[t][this.name])}),e(this).find(".mgjp_mv_protection_toggle").trigger("change","mvJustLoaded")}).on("change",".mgjp_mv_protection_toggle",function(e,t){duration="mvJustLoaded"!==t?400:0,this.checked?i.slideDown(duration):i.slideUp(duration)}).on("change",".mgjp_mv_protection_toggle, .mgjp_mv_permission_select",function(e,i){"mvJustLoaded"!==i&&(n.hasOwnProperty(t)||(n[t]={}),n[t][this.name]="checkbox"===this.type?this.checked:this.value)})}(jQuery); \ No newline at end of file diff --git a/js/min/mv-image-selector.min.js b/js/min/mv-image-selector.min.js new file mode 100644 index 0000000..a649c17 --- /dev/null +++ b/js/min/mv-image-selector.min.js @@ -0,0 +1 @@ +!function(_){"use strict";var e,i,t=_("#mgjp_mv_ir_wrap"),m=_("#mgjp_mv_ir_preview"),a=_("#mgjp_mv_ir_id"),p=_('

'+mgjp_mv_options_media.ir_select_btn+"

"),r=_('

'+mgjp_mv_options_media.ir_restore_btn+"

");i=[p],0_("#mgjp_mv_ir_restore_default").length&&mgjp_mv_options_media.ir_default!==i[0].id?t.append(r):mgjp_mv_options_media.ir_default===i[0].id&&_("#mgjp_mv_ir_restore_default").parent().detach())})}),e.open(),void 0)}).on("click","#mgjp_mv_ir_restore_default",function(){_.post(ajaxurl,{action:"mgjp_mv_restore_default_placeholder_image",nonce:mgjp_mv_options_media.ir_restore_nonce,size:mgjp_mv_options_media.ir_size,args:mgjp_mv_options_media.ir_preview_args},function(e){-1!==e&&0!==e&&e&&(e=JSON.parse(e),a.val(e.id),m.hide().html(e.img).fadeIn(300),_("#mgjp_mv_ir_restore_default").parent().detach(),mgjp_mv_options_media.ir_default=e.id)})})}(jQuery); \ No newline at end of file diff --git a/js/mv-attachment-edit-ltIE9.js b/js/mv-attachment-edit-ltIE9.js new file mode 100644 index 0000000..1079f1c --- /dev/null +++ b/js/mv-attachment-edit-ltIE9.js @@ -0,0 +1,12 @@ +jQuery(function($){ + + var hidden = $('.mgjp-mv-permission-select'); + + $('#mgjp_mv_protection_toggle').change(function(){ + if (this.checked) + hidden.addClass('mgjp-mv-active'); + else + hidden.removeClass('mgjp-mv-active'); + }).change(); + +}(jQuery)); \ No newline at end of file diff --git a/js/mv-attachment-fields.js b/js/mv-attachment-fields.js new file mode 100644 index 0000000..38ca982 --- /dev/null +++ b/js/mv-attachment-fields.js @@ -0,0 +1,46 @@ +(function ($) { + + var vals = {}, + postId, permissionsField; + + $('body') + + .on('mgjpMvLoaded', '#mgjp_mv_attachment_fields', function (event, id) { + postId = id; + permissionsField = $('#mgjp_mv_attachment_permissions_field'); + + if (vals.hasOwnProperty(postId)) { + $(this).find('.mgjp_mv_protection_toggle, .mgjp_mv_permission_select').each(function () { + if (!vals[postId].hasOwnProperty(this.name)) + return; + + if ('checkbox' === this.type) + this.checked = vals[postId][this.name]; + else + this.value = vals[postId][this.name]; + }); + } + + $(this).find('.mgjp_mv_protection_toggle').trigger('change', 'mvJustLoaded'); + }) + + .on('change', '.mgjp_mv_protection_toggle', function (event, justLoaded) { + duration = 'mvJustLoaded' !== justLoaded ? 400 : 0; + + if (this.checked) + permissionsField.slideDown(duration); + else + permissionsField.slideUp(duration); + }) + + .on('change', '.mgjp_mv_protection_toggle, .mgjp_mv_permission_select', function (event, justLoaded) { + if ('mvJustLoaded' === justLoaded) + return; + + if (!vals.hasOwnProperty(postId)) + vals[postId] = {}; + + vals[postId][this.name] = 'checkbox' === this.type ? this.checked : this.value; + }); + +}(jQuery)); \ No newline at end of file diff --git a/js/mv-image-selector.js b/js/mv-image-selector.js new file mode 100644 index 0000000..f1eb4e2 --- /dev/null +++ b/js/mv-image-selector.js @@ -0,0 +1,100 @@ +(function ($) { + 'use strict'; + + + var frame, + buttons, + container = $('#mgjp_mv_ir_wrap'), + preview = $('#mgjp_mv_ir_preview'), + input = $('#mgjp_mv_ir_id'), + select_btn = $('

' + mgjp_mv_options_media.ir_select_btn + '

'), + restore_btn = $('

' + mgjp_mv_options_media.ir_restore_btn + '

'); + + + + buttons = [ select_btn ]; + if (0 < input.val()) + buttons = [ select_btn.children().text(mgjp_mv_options_media.ir_select_btn2).parent() ]; + if (mgjp_mv_options_media.ir_default !== input.val()) + buttons.push(restore_btn); + + + + container + + // append the controls + .append(buttons) + + + // register the media frame creator callback + .on('click', '#mgjp_mv_ir_select_btn', function (e) { + + e.preventDefault(); + + // If the media frame already exists, reopen it. + if (frame) { + frame.open(); + return; + } + + // Create the media frame. + frame = wp.media.frames.mvCustomIR = wp.media({ + 'id' : 'mgjp_mv_select_placeholder_modal', + 'title' : mgjp_mv_options_media.ir_modal_title, + 'library' : { 'type': 'image' }, + 'button' : { 'text': mgjp_mv_options_media.ir_modal_btn } + }); + + // When an image is selected, run a callback. + frame.on('select', function () { + var attachment = frame.state().get('selection').toJSON(); + + $.get(ajaxurl, { + 'action' : 'mgjp_mv_get_attachment_image', + 'id' : attachment[0].id, + 'size' : mgjp_mv_options_media.ir_size, + 'args' : mgjp_mv_options_media.ir_preview_args + }, function (html) { + + if (-1 !== html && 0 !== html && html) { + input.val(attachment[0].id); + preview.hide().html(html).fadeIn(300); + + if (1 > $('#mgjp_mv_ir_restore_default').length && mgjp_mv_options_media.ir_default !== attachment[0].id) { + container.append(restore_btn); + } else if (mgjp_mv_options_media.ir_default === attachment[0].id) { + $('#mgjp_mv_ir_restore_default').parent().detach(); + } + + } + }); + }); + + // Finally, open the modal + frame.open(); + + }) + + // register the restore default callback + .on('click', '#mgjp_mv_ir_restore_default', function () { + + // attempt to restore the default + $.post(ajaxurl, { + 'action' : 'mgjp_mv_restore_default_placeholder_image', + 'nonce' : mgjp_mv_options_media.ir_restore_nonce, + 'size' : mgjp_mv_options_media.ir_size, + 'args' : mgjp_mv_options_media.ir_preview_args + }, function (data) { + + if (-1 !== data && 0 !== data && data) { + // use json2.js to parse json data + data = JSON.parse(data); + input.val(data.id); + preview.hide().html(data.img).fadeIn(300); + $('#mgjp_mv_ir_restore_default').parent().detach(); + mgjp_mv_options_media.ir_default = data.id; + } + }); + }); + +}(jQuery)); \ No newline at end of file diff --git a/mv-ajax-actions.php b/mv-ajax-actions.php new file mode 100644 index 0000000..62cf3b5 --- /dev/null +++ b/mv-ajax-actions.php @@ -0,0 +1,220 @@ + + * @license GPL-3.0+ + */ + + +// forbid direct calls to this file without wp ajax constants +if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { + header( 'Status: 403 Forbidden' ); + header( 'HTTP/1.1 403 Forbidden' ); + exit(); +} + + +/** + * Get the HTML image element of an attachment via AJAX + * + * @since 0.8 + * + * @return string HTML image element of attachment file, + * if there is any, otherwise return 0 + */ +function mgjp_mv_get_attachment_image() { + + $id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : ''; + $size = isset( $_GET['size'] ) ? $_GET['size'] : 'thumbnail'; + $icon = isset( $_GET['icon'] ) ? ! ! $_GET['icon'] : false; + $args = isset( $_GET['args'] ) ? $_GET['args'] : null; + + $html = wp_get_attachment_image( $id, $size, $icon, $args ); + if ( empty( $html ) ) + wp_die( -1 ); + + wp_die( $html ); +} +add_action( 'wp_ajax_mgjp_mv_get_attachment_image', 'mgjp_mv_get_attachment_image' ); + + +/** + * Attempt to restore the default placeholder image + * + * @since 0.8 + * + * @return array [0] + * [1] + */ +function mgjp_mv_restore_default_placeholder_image() { + + if ( ! current_user_can( 'manage_options' ) || ! current_user_can( 'upload_files' ) ) + wp_die( -1 ); + + check_ajax_referer( 'mgjp_mv_ir_restore_default', 'nonce' ); + + $size = isset( $_POST['size'] ) ? $_POST['size']: 'thumbnail'; + $args = isset( $_GET['args'] ) ? $_GET['args'] : null; + + $ir_id = mgjp_mv_load_placeholder_image( true ); + if ( ! $ir_id ) + wp_die( -1 ); + + wp_die( json_encode( array( + 'id' => $ir_id, + 'img' => wp_get_attachment_image( $ir_id, $size, false, $args ) + ) ) ); +} +add_action( 'wp_ajax_mgjp_mv_restore_default_placeholder_image', 'mgjp_mv_restore_default_placeholder_image' ); + + +/** + * Render the Media Vault attachment edit fields in + * the Media Upload modal + * + * @since 0.8.9 + * + * @uses mgjp_mv_get_the_permissions() + * @uses mgjp_mv_is_protected() + * @return array if called in the Media Modal, adds a Media Vault field + * to the attachment fields to edit array + */ +function mgjp_mv_add_attachment_edit_fields( $form_fields, $post ) { + + // only add the field to the Media Upload Modal, and not the attachment + // edit page, we have the Media Vault Protection Settings metabox for + // that job + if ( get_current_screen() !== null ) + return $form_fields; + + $permission = get_post_meta( $post->ID, '_mgjp_mv_permission', true ); + + $permissions = mgjp_mv_get_the_permissions(); + + if ( empty( $permission ) || ! isset( $permissions[$permission] ) ) + $permission = 'default'; + + $default = array( + 'default' => array( + 'select' => __( 'Use Default Setting', 'media-vault' ) + ) + ); + $permissions = $default + $permissions; + + ob_start(); ?> + + + + + + + + + +

+ + + + + +

+ + + + + + + + \ No newline at end of file diff --git a/mv-class-update.php b/mv-class-update.php new file mode 100644 index 0000000..2ef6070 --- /dev/null +++ b/mv-class-update.php @@ -0,0 +1,201 @@ + + * @license GPL-3.0+ + */ + + +/** + * MGJP_MV_Update class handles the necessary + * functions to update the plugin from previous + * versions. + * + * @since 0.8 + * + * @param $version_db string the plugin version as stored in the db + * @param $version_cur string the current plugin version + * @param $option_key string the option_key for the option row where the + * version string is saved in the database + */ +class MGJP_MV_Update { + + /** + * associative array of version numbers below which + * an update is required + * array key = version number less than which this update callback must run + * array value = the update callback to run + * + * @since 0.8 + */ + var $updates = array( + '0.8' => 'update_08', + '0.8.5' => 'update_085' + ); + + /** + * Boolean holds whether the page should reload + * after all the update scripts have run + * + * @since 0.8.5 + */ + var $force_reload = false; + + /** + * Compare the current version with the version updated + * from, determine the update functions that are required + * to run and then run them sequentially + * + * @since 0.8 + * + * @param $version_db string the plugin version as stored in the db + * @param $version_cur string the current plugin version + * @param $option_key string the option_key for the option row where the + * version string is saved in the database + */ + function __construct( $version_db, $version_cur, $option_key ) { + + $versions = array_keys( $this->updates ); + + foreach ( $versions as $version ) { + if ( version_compare( $version_db, $version, 'lt' ) ) { + $updates_start = $version; + break; + } + } + + if ( ! isset( $updates_start ) ) + return update_site_option( $option_key, $version_cur ); + + $updates_todo = array_slice( + $this->updates, + array_search( + $updates_start, + $versions + ) ); + + foreach ( $updates_todo as $update ) { + if ( is_callable( array( &$this, $update ) ) ) + call_user_func( array( &$this, $update ) ); + } + + update_site_option( $option_key, $version_cur ); + + if ( ! $this->force_reload ) + return; + + $current_url = esc_url_raw( '//' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + + if ( headers_sent() ) + echo ''; + else + wp_redirect( $current_url ); + exit; + } + + /** + * Updates plugin data from pre-version 0.8 to version 0.8 + * Loads the Media Vault place-holder image + * which is used from 0.8 onwards to replace + * images a user does not have permission to view. + * Modifies the db replacing all references to the deprecated + * `mgjp_mv_meta` post meta key with the new `_mgjp_mv_permission` + * post meta key. + * + * @since 0.8 + * + * @uses mgjp_mv_load_placeholder_image() + */ + function update_08() { + + // edit existing options + $default_permission = get_option( 'mgjp_mv_default_permission', 'logged-in' ); + delete_option( 'mgjp_mv_default_permission' ); + add_option( 'mgjp_mv_default_permission', $default_permission, '', 'yes' ); + + // add options + add_option( 'mgjp_mv_ir', array( 'is_on' => true ), '', 'no' ); + + // load place-holder image into Media Library + mgjp_mv_load_placeholder_image(); + + /** correctly replace old `mgjp_mv_meta` meta with new `_mgjp_mv_permission` meta **/ + global $wpdb; + + // get all posts with the old 'mgjp_mv_meta' meta key + $old = $wpdb->get_results( + $wpdb->prepare( + " + SELECT meta_id, meta_value + FROM $wpdb->postmeta + WHERE meta_key = %s + ", + 'mgjp_mv_meta' + ), ARRAY_A + ); + + if ( empty( $old ) ) + return; + + // distill the meta values which have custom + // permissions set on them + foreach ( $old as $columns ) { + $meta = unserialize( $columns['meta_value'] ); + if ( ! isset( $meta['permission'] ) ) + continue; + $ids[] = $columns['meta_id']; + $data[$meta['permission']][] = $columns['meta_id']; + } + + if ( ! isset( $data ) ) + return delete_post_meta_by_key( 'mgjp_mv_meta' ); + + // build the sql update query to convert the old meta system + // using 'mgjp_mv_meta' to the new meta system using '_mgjp_mv_permission' + $sql_update[] = $wpdb->prepare( "UPDATE `$wpdb->postmeta` SET `meta_key` = %s, `meta_value` = CASE", '_mgjp_mv_permission' ); + foreach ( $data as $meta_value => $meta_ids ) { + if ( isset( $meta_ids[1] ) ) + $sql_update[] = $wpdb->prepare( "WHEN `meta_id` IN (" . implode( ', ', array_fill( 0, count( $meta_ids ), '%d' ) ) . ") THEN %s", array_merge( $meta_ids, array( $meta_value ) ) ); + else + $sql_update[] = $wpdb->prepare( "WHEN `meta_id` = %d THEN %s", $meta_ids[0], $meta_value ); + } + $sql_update[] = $wpdb->prepare( "ELSE %s END WHERE `meta_id` IN (" . implode( ', ', array_fill( 0, count( $ids ), '%d' ) ) . ")", array_merge( array( 'logged-in' ), $ids ) ); + + // run the update query + $wpdb->query( implode( ' ', $sql_update ) ); + + // and delete all other references to 'mgjp_mv_meta' + delete_post_meta_by_key( 'mgjp_mv_meta' ); + } + + /** + * Verifies that the rewrite rules required for Media Vault + * to function correctly are set and functioning. If they are + * it enables all the plugin's functionality and sets the + * force_reload flag for the update class + * + * @since 0.8.5 + * + * @uses mgjp_mv_check_rewrite_rules() + */ + function update_085() { + + if ( ! mgjp_mv_check_rewrite_rules() ) + return; + + update_site_option( 'mgjp_mv_enabled', true ); + + $this->force_reload = true; + + } + +} // END of class MGJP_MV_Update + + +?> \ No newline at end of file diff --git a/mv-extra-activation-steps.php b/mv-extra-activation-steps.php new file mode 100644 index 0000000..89199a7 --- /dev/null +++ b/mv-extra-activation-steps.php @@ -0,0 +1,253 @@ + + * @license GPL-3.0+ + */ + + + +/** + * Required to verify rewrite rules are functioning + * correctly when the plugin is not fully enabled + * + * @since 0.8.5 + */ +function mgjp_mv_check_rewrite_rules_answer() { + if ( isset( $_GET['mgjp_mv_file'] ) && ! empty( $_GET['mgjp_mv_file'] ) + && isset( $_GET['mgjp_mv_rewrite_test'] ) && $_GET['mgjp_mv_rewrite_test'] ) + die( 'pass' ); +} +add_action( 'init', 'mgjp_mv_check_rewrite_rules_answer', 0 ); + + +/** + * Display a notice in WP admin to the Admins to prompt + * them to do the extra steps to fully activate the + * Media Vault plugin + * + * @since 0.8.5 + */ +function mgjp_mv_extra_activation_steps_notice() { + + // only show to admins on single site install or + // network admins on multisite install + if ( ! current_user_can( 'install_plugins' ) ) + return; + + $screen = get_current_screen(); + if ( ! in_array( $screen->id, array( 'plugins-network', 'plugins', 'options-media', 'upload', 'media', 'attachment' ) ) ) + return; + + mgjp_mv_admin_notice( + '' . __( 'Almost there!', 'media-vault' ) . ' - ' . __( 'Because of your setup, Media Vault requires some extra steps before it is enabled. Follow the instructions and then go protect some files!', 'media-vault' ), + array( + 'link' => network_admin_url( 'plugins.php?page=mgjp-mv-eas' ), + 'text' => __( 'Fully Activate Media Vault', 'media-vault' ) + ) + ); + +} +add_action( 'admin_notices', 'mgjp_mv_extra_activation_steps_notice' ); +add_action( 'network_admin_notices', 'mgjp_mv_extra_activation_steps_notice' ); + + +/** + * Adds an admin page to the plugins admin menu dropdown. + * The page displays instructions to admins to fully activate + * the Media Vault plugin + * + * @since 0.8.5 + */ +function mgjp_mv_extra_activation_steps_page() { + + if ( is_multisite() && ! is_network_admin() ) + return; + + add_submenu_page( + 'plugins.php', + __( 'Media Vault Activation Helper', 'media-vault' ), + __( 'Media Vault Activation', 'media-vault' ), + 'install_plugins', + 'mgjp-mv-eas', + 'mgjp_mv_render_extra_activation_steps_page' + ); + +} +add_action( 'admin_menu', 'mgjp_mv_extra_activation_steps_page' ); +add_action( 'network_admin_menu', 'mgjp_mv_extra_activation_steps_page' ); + + +/** + * Render the page + * + * @since 0.8.5 + */ +function mgjp_mv_render_extra_activation_steps_page() { + + wp_enqueue_style( 'mgjp-mv-eas-page', plugins_url( 'css/mv-eas-page.css', __FILE__ ), 'all', null ); + + global $is_apache; + + $home_path = get_home_path(); + $rewrite_rules_enabled = mgjp_mv_check_rewrite_rules(); + $eas_supported = $is_apache; + + if ( isset( $_POST['enable_mediavault'] ) ) { + if ( $rewrite_rules_enabled ) { + check_admin_referer( 'mgjp_mv_enable_media_vault' ); + ?> +
+

+ ' . esc_html__( 'files', 'media-vault' ) . '' ); ?> +

+
+ +
+

+ +

+
+ + +
+ +

+ Media Vault Logo + +

+ + + +

+ ' . esc_html__( 'Media files', 'media-vault' ) . '', '' . esc_html__( 'uploading new files', 'media-vault' ) . '', '' . esc_html__( 'settings', 'media-vault' ) . '' ); ?> +

+ + +

+ + ' . esc_html__( 'support forum', 'media-vault' ) . '' ); ?> + +

+ + + + +

+ Apache Server' ); + + if ( is_multisite() ) + $errors['Multisite'] = sprintf( esc_html_x( 'you are running a %s installation', 'as in: "you are on a WordPress Multisite installation"', 'media-vault' ), 'WordPress MultiSite' ); + + if ( ! isset( $errors ) && ! get_option( 'permalink_structure' ) ) + $errors['Nopretty'] = sprintf( esc_html_x( 'you do not have %s enabled', 'as in: "you do not have Pretty Permalinks enabled"', 'media-vault' ), '' . esc_html__( 'Pretty Permalinks' ) . '' ); + + if ( ! isset( $errors ) && ! is_writable( $home_path . '.htaccess' ) ) + $errors['Nonwritable'] = sprintf( esc_html__( 'the site\'s %s file is not writable', 'as in: "the site\'s .htaccess file is not writable "', 'media-vault' ), '.htaccess' ); + + if ( isset( $errors ) ) { + + $error_txt = ''; + $last_error = array_pop( $errors ); + if ( count( $errors ) > 0 ) + $error_txt .= implode( ', ', $errors ) . ' ' . esc_html__( 'and', 'media-vault' ) . ' '; + $error_txt .= $last_error . ','; + + printf( esc_html_x( 'However, because %s the plugin was unable to successfully update the rewrite rules for this site programmatically.', 'as in: "Because *you are running WordPress MultiSite* Media Vault cannot do it automatically"', 'media-vault' ), $error_txt ); + + } else { + + esc_html_e( 'However for some reason the plugin was unable to successfully update the rewrite rules for this site.', 'media-vault' ); + + } + + echo ' '; + + echo wp_kses( __( 'In order to manually fully activate Media Vault on your setup please carefully follow the instructions below:', 'media-vault' ), array( 'strong' => array() ), false ); ?> +

+ +
    + + +
  1. +

    + !: ' . esc_html__( 'requires' ) . '', 'mod_rewrite', 'Apache' ); ?> +

    +
  2. + + +
  3. + + +

    + .htaccess'; + $rewrite_file_loc = '' . $home_path . ''; + $rewrite_rule_loc = sprintf( wp_kses( __( 'in the WordPress rewrite block (the WordPress block usually starts with %s and ends with %s), just below the line reading %s', 'media-vault' ), array( 'strong' => array() ), false ), '# BEGIN WordPress', '# END WordPress', 'RewriteRule ^index\.php$ - [L]' ); + + if ( ! is_multisite() && ! get_option( 'permalink_structure' ) ) { + + $rewrite_rule_loc = __( 'above any other rewrite rules in the file.', 'media-vault' ); + + printf( wp_kses( __( 'Media Vault works best with %s enabled, so it is strongly recommended that you %s! If, however, you really really want to use ugly permalinks, then...', 'media-vault' ), array( 'i' => array() ), false ), '' . esc_html__( 'Pretty Permalinks', 'media-vault' ) . '', '' . esc_html__( 'enable them', 'media-vault' ) . '' ); + echo "\n"; + } + + printf( esc_html__( 'Add the following to your %s file in %s', 'media-vault' ), $rewrite_file_type, $rewrite_file_loc ); + echo ' ', $rewrite_rule_loc; + ?> +

    + +

    + +

    +

    + +

    + + + + + +
  4. + +
  5. +

    + +

    +
    + + +
    +
  6. + +
+ + + +
+ + \ No newline at end of file diff --git a/mv-extra-deactivation-steps.php b/mv-extra-deactivation-steps.php new file mode 100644 index 0000000..21ae81a --- /dev/null +++ b/mv-extra-deactivation-steps.php @@ -0,0 +1,233 @@ + + * @license GPL-3.0+ + */ + + + +/** + * Display a notice in WP admin to the Admins to prompt + * them to do the extra steps to fully deactivate the + * Media Vault plugin + * + * @since 0.8.5 + */ +function mgjp_mv_extra_deactivation_steps_notice() { + + // only show to admins on single site install or + // network admins on multisite install + if ( ! current_user_can( 'install_plugins' ) ) + return; + + $screen = get_current_screen(); + if ( is_multisite() ) { + if ( 'plugins-network' !== $screen->id ) + return; + } else { + if ( 'plugins' !== $screen->id ) + return; + } + + if ( 'disallowed' !== get_site_option( 'mgjp_mv_deactivation' ) ) + return; + + mgjp_mv_admin_notice( + '' . __( 'Almost done!', 'media-vault' ) . ' - ' . __( 'Because of your setup, Media Vault requires some extra steps before it is deactivated. If you really want to deactivate, just click the button and follow the instructions!', 'media-vault' ), + array( + array( + 'link' => network_admin_url( 'plugins.php?page=mgjp-mv-eds' ), + 'text' => __( 'Fully Deactivate Media Vault', 'media-vault' ) + ), + array( + 'link' => network_admin_url( 'plugins.php?page=mgjp-mv-eds&cancel_deactivation=1&_wpnonce=' . wp_create_nonce( 'mgjp_mv_deactivation' ) ), + 'text' => __( 'Cancel Deactivation', 'media-vault' ) + ) + ) + ); + +} +add_action( 'admin_notices', 'mgjp_mv_extra_deactivation_steps_notice' ); +add_action( 'network_admin_notices', 'mgjp_mv_extra_deactivation_steps_notice' ); + + +/** + * Adds an admin page to the plugins admin menu dropdown. + * The page displays instructions to admins to fully deactivate + * the Media Vault plugin + * + * @since 0.8.5 + */ +function mgjp_mv_extra_deactivation_steps_page() { + + if ( is_multisite() && ! is_network_admin() ) + return; + + add_submenu_page( + 'plugins.php', + __( 'Media Vault Deactivation Helper', 'media-vault' ), + __( 'Media Vault Deactivation', 'media-vault' ), + 'install_plugins', + 'mgjp-mv-eds', + 'mgjp_mv_render_extra_deactivation_steps_page' + ); + +} +add_action( 'admin_menu', 'mgjp_mv_extra_deactivation_steps_page' ); +add_action( 'network_admin_menu', 'mgjp_mv_extra_deactivation_steps_page' ); + + +/** + * Render the page + * + * @since 0.8.5 + */ +function mgjp_mv_render_extra_deactivation_steps_page() { + + wp_enqueue_style( 'mgjp-mv-eas-page', plugins_url( 'css/mv-eas-page.css', __FILE__ ), 'all', null ); + + global $is_apache; + + $home_path = get_home_path(); + $rewrite_rules_enabled = mgjp_mv_check_rewrite_rules( true ); + $eds_supported = $is_apache; + + if ( isset( $_POST['true_deactivation'] ) ) { + if ( $rewrite_rules_enabled ) { + ?> +
+

+ At least one Media Vault rewrite rule is still functional. Media Vault will not be properly deactivated if the rewrite rules are not removed because they will cause problems when attempting to access files that are in the Media Vault protected folders.', 'media-vault' ), array( 'em' => array(), 'strong' => array() ) ); ?> +

+

+ +

+
+ + +
+ +

+ Media Vault Logo + +

+ +

+ Apache Server' ); + + if ( is_multisite() ) + $errors['Multisite'] = sprintf( esc_html_x( 'you are running a %s installation', 'as in: "you are on a WordPress Multisite installation"', 'media-vault' ), 'WordPress MultiSite' ); + + if ( ! isset( $errors ) && ! get_option( 'permalink_structure' ) ) + $errors['Nopretty'] = sprintf( esc_html_x( 'you do not have %s enabled', 'as in: "you do not have Pretty Permalinks enabled"', 'media-vault' ), '' . esc_html__( 'Pretty Permalinks' ) . '' ); + + if ( ! isset( $errors ) && ! is_writable( $home_path . '.htaccess' ) ) + $errors['Nonwritable'] = sprintf( esc_html__( 'the site\'s %s file is not writable', 'as in: "the site\'s .htaccess file is not writable "', 'media-vault' ), '.htaccess' ); + + if ( isset( $errors ) ) { + + $error_txt = ''; + $last_error = array_pop( $errors ); + if ( count( $errors ) > 0 ) + $error_txt .= implode( ', ', $errors ) . ' ' . esc_html__( 'and', 'media-vault' ) . ' '; + $error_txt .= $last_error . ','; + + printf( esc_html_x( 'However, because %s the plugin was unable to successfully update the rewrite rules for this site programmatically.', 'as in: "Because *you are running WordPress MultiSite* Media Vault cannot do it automatically"', 'media-vault' ), $error_txt ); + + } else { + + esc_html_e( 'However for some reason the plugin was unable to successfully update the rewrite rules for this site.', 'media-vault' ); + + } + + printf( wp_kses( __( 'In order to manually fully %s Media Vault on your setup please carefully follow the instructions below:', 'media-vault' ), array( 'strong' => array() ), false ), 'deactivate' ); + ?> +

+

+ + temporarily deactivate Media Vault and do not mind leaving the rewrite rules functioning, simply click the "Temporarily Deactivate Media Vault" button. However, if you are planning on permanently deactivating Media Vault make sure to follow the steps below, otherwise you may experience problems when trying to access attachment files still in the Media Vault protected folders.', 'media-vault' ), array( 'strong' => array() ) ); ?> + +

+ +
    + +
  1. + +

    + .htaccess'; + $rewrite_file_loc = '' . $home_path . ''; + + printf( wp_kses( __( 'From your %s file in %s, remove all the code between the lines starting with %s and ending with %s.', 'media-vault' ), array( 'strong' => array() ) ), $rewrite_file_type, $rewrite_file_loc, '# Media Vault Rewrite Rules', '# Media Vault Rewrite Rules End' ); + ?> +

    + +

    + ' . esc_html__( 'support forum', 'media-vault' ) . '' ); ?> +

    + +
  2. + +
  3. +

    + +

    +
    + + + + +
    +
  4. + +
+ +
+ + + * @license GPL-3.0+ + */ + + +/** + * Check if file with path $rel_file from WP uploads folder is in a Media Vault protected folder. + * If it is, verify the user requesting it has permission to access it. After they pass the check, + * If the 'safeforce' flag has been set for $action, send HTTP Headers forcing file download, + * otherwise send normal headers and serve the file. + * + * @since 0.1 + * + * @uses mgjp_mv_upload_dir() + * @uses mgjp_mv_get_the_permissions() + * @param string $rel_file Filesystem path or filename, must be relative to the WP uploads folder + * @param string $action Force Download Flag, only acceptable value is 'safeforce' + */ +function mgjp_mv_get_file( $rel_file, $action = '' ) { + + // $rel_file = path to the file to view/download, + // relative to the WP uploads folder + // (eg:'/media-vault/2013/10/media-vault-150x150.jpg') + + $upload_dir = wp_upload_dir(); + + // only files in the WP uploads directory are allowed to be accessed: + $file = rtrim( $upload_dir['basedir'], '/' ) . str_replace( '..', '', isset( $rel_file ) ? $rel_file : '' ); + + //---Basic Checks----------------------------------------------------// + + if ( ! $upload_dir['basedir'] || ! is_file( $file ) ) { + status_header( 404 ); + wp_die( '404. File not found.' ); + } + + $mime = wp_check_filetype( $file ); // Check filetype against allowed filetypes + + if ( isset( $mime['type'] ) && $mime['type'] ) { + $mimetype = $mime['type']; + } else { + status_header( 403 ); + wp_die( __( '403. Forbidden.
You cannot directly access files of this type in this directory on this server. Please contact the website administrator.' ) ); + } + + //---Permission Checks-----------------------------------------------// + + $file_info = pathinfo( $rel_file ); + + // check if file is protected by checking + // if it is in the protected folder before + // doing any permission checks + if ( 0 === stripos( $file_info['dirname'] . '/', mgjp_mv_upload_dir( '/', true ) ) ) { + + // disable caching of this page by caching plugins ------// + if ( ! defined( 'DONOTCACHEPAGE' ) ) + define( 'DONOTCACHEPAGE', 1 ); + + if ( ! defined( 'DONOTCACHEOBJECT' ) ) + define( 'DONOTCACHEOBJECT', 1 ); + + if ( ! defined( 'DONOTMINIFY' ) ) + define( 'DONOTMINIFY', 1 ); + + //-------------------------------------------------------// + + // try and get attachment id from url -------------------// + global $wpdb; + $attachments = $wpdb->get_results( + $wpdb->prepare( + " + SELECT post_id, meta_value + FROM $wpdb->postmeta + WHERE meta_key = %s + AND meta_value LIKE %s + ", + '_wp_attachment_metadata', + '%' . $file_info['basename'] . '%' + ), ARRAY_A + ); + + $attachment_id = false; + foreach ( $attachments as $attachment ) { + + $meta_value = unserialize( $attachment['meta_value'] ); + + if ( ltrim( dirname( $meta_value['file'] ), '/' ) == ltrim( $file_info['dirname'], '/' ) ) { + $attachment_id = $attachment['post_id']; + break; + } + } + // ------------------------------------------------------// + + if ( ! $permission = mgjp_mv_get_the_permission( $attachment_id ) ) + $permission = get_option( 'mgjp_mv_default_permission', 'logged-in' ); + + $permissions = mgjp_mv_get_the_permissions(); + + // permission set up error detection + $standard_error_txt = ' ' . esc_html__( 'Therefore for safety and privacy reasons this file is unavailable. Please contact the website administrator.', 'media-vault' ) . '

←' . esc_html__( 'Return to homepage', 'media-vault' ) .'

'; + + if ( ! isset( $permissions[$permission] ) ) + wp_die( __( 'The permissions set for this file are not recognized.', 'media-vault' ) . $standard_error_txt ); + + if ( ! isset( $permissions[$permission]['logged_in'] ) ) + $errors[] = 'logged_in'; + if ( ! isset( $permissions[$permission]['cb'] ) ) + $errors[] = 'cb'; + if ( isset( $errors ) ) { + $error_txt = __( 'The permissions set for this file have left the following important parameters undefined:', 'media-vault' ) + . '' + . '

' . $standard_error_txt . '

'; + wp_die( $error_txt ); + } + + if ( $permissions[$permission]['logged_in'] ) + is_user_logged_in() || auth_redirect(); // using is_user_logged_in is lighter than using just auth_redirect + + if ( false !== $permissions[$permission]['cb'] ) { + + if ( ! is_callable( $permissions[$permission]['cb'] ) ) + wp_die( __( 'The permission checking function set in this file\'s permissions is not callable.', 'media-vault' ) . $standard_error_txt ); + + $permission_check = call_user_func_array( $permissions[$permission]['cb'], array( $attachment_id, $rel_file, $file ) ); + + if ( is_wp_error( $permission_check ) ) + wp_die( $permission_check->get_error_message() . $standard_error_txt ); + + if ( true !== $permission_check ) + wp_die( __( 'You do not have sufficient permissions to view this file.', 'media-vault' ) . $standard_error_txt ); + } + + } // end of permission checks + + //-------------------------------------------------------------------// + + header( 'Content-Type: ' . $mimetype ); // always send this + if ( false === strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) ) + header( 'Content-Length: ' . filesize( $file ) ); + + if ( 'safeforce' !== $action ) { + //--OPEN FILE IN BROWSER functions-------------// + + $last_modified = gmdate( 'D, d M Y H:i:s', filemtime( $file ) ); + $etag = '"' . md5( $last_modified ) . '"'; + header( "Last-Modified: $last_modified GMT" ); + header( 'ETag: ' . $etag ); + header( 'Cache-Control: no-store, no-cache, must-revalidate' ); // HTTP 1.1. + header( 'Pragma: no-cache' ); // HTTP 1.0. + header( 'Expires: Thu, 01 Dec 1994 16:00:00 GMT' ); // Proxies + + // Support for Conditional GET + $client_etag = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) : false; + + if( ! isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) + $_SERVER['HTTP_IF_MODIFIED_SINCE'] = false; + + $client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); + // If string is empty, return 0. If not, attempt to parse into a timestamp + $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0; + + // Make a timestamp for our most recent modification... + $modified_timestamp = strtotime( $last_modified ); + + if ( ( $client_last_modified && $client_etag ) + ? ( ( $client_modified_timestamp >= $modified_timestamp ) && ( $client_etag == $etag ) ) + : ( ( $client_modified_timestamp >= $modified_timestamp ) || ( $client_etag == $etag ) ) + ) { + status_header( 304 ); + exit; + } + + } else { + //--FORCE DOWNLOAD Functions-----------------------// + + // required for IE, otherwise Content-disposition is ignored + if( ini_get( 'zlib.output_compression' ) ) + ini_set( 'zlib.output_compression', 'Off' ); + + header( 'Pragma: public' ); // required + header( 'Expires: 0' ); + header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' ); + header( 'Cache-Control: private', false ); // required for certain browsers + header( 'Content-Disposition: attachment; filename="' . $file_info['basename'] . '";' ); + header( 'Content-Transfer-Encoding: binary' ); + + } + + // If we made it this far, just serve the file + if ( ob_get_length() ) + ob_clean(); + + flush(); + + readfile( $file ); + exit; +} \ No newline at end of file diff --git a/mv-metaboxes.php b/mv-metaboxes.php new file mode 100644 index 0000000..d7a85fe --- /dev/null +++ b/mv-metaboxes.php @@ -0,0 +1,178 @@ + + * @license GPL-3.0+ + */ + + +/** Register custom metabox **/ +add_meta_box( + 'mgjp_mv_protection_metabox', + __( 'Media Vault Protection Settings', 'media-vault' ), + 'mgjp_mv_render_attachment_protection_metabox', + 'attachment', + 'side' +); + + +/** + * Enqueue metabox styles in head of attachment + * edit page + * + * @since 0.8.9 + */ +function mgjp_mv_attachment_protection_metabox_styles_and_scripts() { + + $screen = get_current_screen(); + if ( 'attachment' !== $screen->id ) + return; + + // enqueue metabox styles + wp_enqueue_style( 'mgjp-mv-att-edit-css', plugins_url( 'css/mv-attachment-edit.css', __FILE__ ), 'all', null ); + +} +add_action( 'admin_enqueue_scripts', 'mgjp_mv_attachment_protection_metabox_styles_and_scripts' ); + + +/** + * Rendering function for the Media Vault attachment + * metabox + * + * @since 0.7.1 + * + * @uses mgjp_mv_get_the_permissions() + * @uses mgjp_mv_is_protected() + * @param $post object WP_Post object of current attachment + */ +function mgjp_mv_render_attachment_protection_metabox( $post ) { + + + wp_nonce_field( 'mgjp_mv_protection_metabox', 'mgjp_mv_protection_metabox_nonce' ); + + + $permission = get_post_meta( $post->ID, '_mgjp_mv_permission', true ); + + $permissions = mgjp_mv_get_the_permissions(); + + if ( empty( $permission ) || ! isset( $permissions[$permission] ) ) + $permission = 'default'; + + $default = array( + 'default' => array( + 'select' => __( 'Use Default Setting', 'media-vault' ) + ) + ); + $permissions = $default + $permissions; ?> + + + + + ID ) ); ?>> + + + +

+ + + +

+ + \ No newline at end of file diff --git a/mv-options-media-library.php b/mv-options-media-library.php new file mode 100644 index 0000000..932931d --- /dev/null +++ b/mv-options-media-library.php @@ -0,0 +1,294 @@ + + * @license GPL-3.0+ + */ + + + +/** + * Remove WP List Table row actions in the Media Library List Table + * if the attachment is protected and the user is not permitted to access it + * + * @since 0.7 + * + * @uses mgjp_mv_check_user_permitted() returns true if user is permitted to access + * specified attachment + * @param $actions array Array of row actions available for specific attachment + * @param $post object WP_Post object of currently rendering attachment + * @return array Return row actions untouched if user permitted to access attachment + * @return array Empty array if no access permitted + */ +function mgjp_mv_modify_media_library_row_actions( $actions, $post ) { + + // check if current user is permitted to access the post + if ( ! mgjp_mv_check_user_permitted( $post->ID ) ) + return array( esc_html__( 'You do not have permission to access this attachment', 'media-vault' ) ); + + return $actions; +} +add_filter( 'media_row_actions', 'mgjp_mv_modify_media_library_row_actions', 10, 2 ); + + +/** + * Register Media Vault custom column to WP Media Library (wp-admin/upload.php) + * list table. + * + * @since 0.4 + * + * @param array $columns array of columns for WP Media List Table + * @return array Array of columns, including custom column, for WP Media List Table + */ +function mgjp_mv_register_media_library_custom_column( $columns ) { + + $columns['mgjp_mv_info'] = 'Media Vault'; + + return $columns; +} +add_filter( 'manage_upload_columns', 'mgjp_mv_register_media_library_custom_column' ); + + +/** + * Render function for Media Vault custom column in WP Media Library list table. + * + * @since 0.4 + * + * @uses mgjp_mv_get_the_permissions() + * @param $column_name string name-id of current column + * @param $post_id int ID of post being evaluated + */ +function mgjp_mv_render_media_library_custom_column( $column_name, $post_id ) { + + if ( 'mgjp_mv_info' != $column_name ) + return; + + if ( ! $permission = mgjp_mv_get_the_permission( $post_id ) ) + return; + + $permissions = mgjp_mv_get_the_permissions(); + + $permission = isset( $permissions[$permission] ) ? $permissions[$permission] : ''; + + $description = isset( $permission['description'] ) && ! empty( $permission['description'] ) ? + esc_html( $permission['description'] ) : + '' + . esc_html__( 'Undetermined! Permissions have been misconfigured for this attachment!', 'media-vault' ) + . ''; ?> + + + +

+ +

+ + + +

+ + + + + + + + + + id ) { + + if ( isset( $_REQUEST['mgjp-mv-protected'] ) && (int) $_REQUEST['mgjp-mv-protected'] ) { + $message = sprintf( + _n( + 'Media file is now protected.', //singular + '%s media files are now protected.', //plural + $_REQUEST['mgjp-mv-protected'], + 'media-vault' + ), number_format_i18n( $_REQUEST['mgjp-mv-protected'] ) + ); + echo '

' . esc_html( $message ) . '

'; + $_SERVER['REQUEST_URI'] = remove_query_arg( 'mgjp-mv-protected', $_SERVER['REQUEST_URI'] ); + } + + if ( isset( $_REQUEST['mgjp-mv-unprotected'] ) && (int) $_REQUEST['mgjp-mv-unprotected'] ) { + $message = sprintf( + _n( + 'Removed file protection on media file.', //singular + 'Removed file protection on %s media files.', //plural + $_REQUEST['mgjp-mv-unprotected'], + 'media-vault' + ), number_format_i18n( $_REQUEST['mgjp-mv-unprotected'] ) + ); + echo '

' . esc_html( $message ) . '

'; + $_SERVER['REQUEST_URI'] = remove_query_arg( 'mgjp-mv-unprotected', $_SERVER['REQUEST_URI'] ); + } + + } +} +add_action( 'admin_notices', 'mgjp_mv_add_media_library_admin_notices' ); + + + +/** Handle Media Vault bulk actions **/ +$wp_list_table = _get_list_table( 'WP_Media_List_Table' ); +$action = $wp_list_table->current_action(); + +$allowed_actions = array( + 'mgjp-mv-protect', + 'mgjp-mv-unprotect' +); +if ( ! in_array( $action, $allowed_actions ) ) return; + +check_admin_referer( 'bulk-media' ); + +if ( isset( $_REQUEST['media'] ) ) + $media_ids = array_map( 'intval', $_REQUEST['media'] ); + +if ( empty( $media_ids ) ) return; + +$location = 'upload.php'; +if ( $referer = wp_get_referer() ) { + if ( false !== strpos( $referer, 'upload.php' ) ) + $location = remove_query_arg( + array( 'mgjp-mv-protected', 'mgjp-mv-unprotected', 'trashed', 'untrashed', 'deleted', 'message', 'ids', 'posted' ), + $referer + ); +} + +$pagenum = $wp_list_table->get_pagenum(); +if ( $pagenum > 1 ) + $location = add_query_arg( 'paged', $pagenum, $location ); + +require_once( plugin_dir_path( __FILE__ ) . 'includes/mgjp-functions.php' ); + +switch( $action ) { + + case 'mgjp-mv-protect': + if ( ! current_user_can( 'edit_posts' ) ) + wp_die( __( 'You are not allowed to add attachments to the protected directory.', 'media-vault' ) ); + + $protected = 0; + foreach ( (array) $media_ids as $media_id ) { + + if ( ! current_user_can( 'edit_post', $media_id ) ) + continue; + + if ( mgjp_mv_is_protected( $media_id ) ) + continue; + + $move = mgjp_mv_move_attachment_to_protected( $media_id ); + + if ( is_wp_error( $move ) ) + wp_die( __( 'There was an error moving the files to the protected directory.', 'media-vault' ) . '
' . $move->get_error_message() ); + + $protected++; + } + + $location = add_query_arg( array( + 'mgjp-mv-protected' => $protected, + 'ids' => join( ',', $media_ids ) + ), $location ); + break; + + case 'mgjp-mv-unprotect': + if ( ! current_user_can( 'edit_posts' ) ) + wp_die( __( 'You are not allowed to remove attachments from the protected directory.', 'media-vault' ) ); + + $unprotected = 0; + foreach ( (array) $media_ids as $media_id ) { + + if ( ! current_user_can( 'edit_post', $media_id ) ) + continue; + + if ( ! mgjp_mv_is_protected( $media_id ) ) + continue; + + $move = mgjp_mv_move_attachment_from_protected( $media_id ); + + if ( is_wp_error( $move ) ) + wp_die( __( 'There was an error moving the files from the protected directory.', 'media-vault' ) . '
' . $move->get_error_message() ); + + delete_post_meta( $media_id, '_mgjp_mv_permission' ); + + $unprotected++; + } + + $location = add_query_arg( array( + 'mgjp-mv-unprotected' => $unprotected, + 'ids' => join( ',', $media_ids ) + ), $location ); + break; + + default: return; +} + +$location = remove_query_arg( array( 'action', 'action2', 'media' ), $location ); + +wp_redirect( $location ); +exit(); \ No newline at end of file diff --git a/mv-options-media-new.php b/mv-options-media-new.php new file mode 100644 index 0000000..a4bc479 --- /dev/null +++ b/mv-options-media-new.php @@ -0,0 +1,139 @@ + + * @license GPL-3.0+ + */ + + +/** + * Add custom styles to the media upload page + * + * @since 0.2 + */ +function mgjp_mv_media_new_options_css() { + + $screen = get_current_screen(); + if ( 'media' == $screen->base && 'add' == $screen->action ) + wp_enqueue_style( 'mgjp-mv-media-new-styles', plugins_url( 'css/mv-media-new.css', __FILE__ ), 'all', null ); + +} +add_action( 'admin_enqueue_scripts', 'mgjp_mv_media_new_options_css' ); + + +/** + * Js for uploads page updates a plupload var controlling + * whether an upload is moved to the protected directory + * or not. + * + * @since 0.2 + */ +function mgjp_mv_media_new_options_js() { ?> + + + + base && 'add' == $screen->action ) : ?> + + + + + + + + + + + +
+ + + + + +
+ + base && 'add' == $screen->action ) : ?> + +
+ + + +
+ + \ No newline at end of file diff --git a/mv-options-media-vault.php b/mv-options-media-vault.php new file mode 100644 index 0000000..bfe3ed5 --- /dev/null +++ b/mv-options-media-vault.php @@ -0,0 +1,309 @@ + + * @license GPL-3.0+ + */ + + +/** Register plugin settings **/ +register_setting( 'media', 'mgjp_mv_default_permission' ); +register_setting( 'media', 'mgjp_mv_options', 'mgjp_mv_options_sanitize' ); +register_setting( 'media', 'mgjp_mv_ir', 'mgjp_mv_ir_sanitize' ); + + +add_settings_section( + 'mgjp_mv_general_settings', + null, + 'mgjp_mv_render_general_settings_info_txt', + 'media' +); + + +add_settings_field( + 'default_permission', + __( 'Default Protected File Permissions', 'media-vault' ), + 'mgjp_mv_render_default_permission_field', + 'media', + 'mgjp_mv_general_settings', + array( 'label_for' => 'mgjp_mv_default_permission' ) +); + +add_settings_field( + 'default_upload_protection', + __( 'Default Upload Protection', 'media-vault' ), + 'mgjp_mv_render_checkbox_field', + 'media', + 'mgjp_mv_general_settings', + array( + 'label_for' => 'mgjp_mv_default_upload_protection', + 'option' => 'mgjp_mv_options', + 'option_id' => 'default_upload_protection', + 'value' => 'on', + 'desc' => __( 'Set media file upload protection to be enabled by default when uploading new files through the Add New Media page in the WordPress Admin.', 'media-vault' ) + ) +); + +add_settings_field( + 'place_holder_img', + __( 'Image Placeholder', 'media-vault' ), + 'mgjp_mv_render_place_holder_img_field', + 'media', + 'mgjp_mv_general_settings' +); + + +/** + * Sanitization function for mgjp_mv_option settings + * + * @since 0.8 + * + * @param $input array of options from settings page + * @return array sanitized array of mgjp_mv_options + */ +function mgjp_mv_options_sanitize( $input ) { + + $options = get_option( 'mgjp_mv_options' ); + + $options['default_upload_protection'] = isset( $input['default_upload_protection'] ) ? 'on' : 'off'; + + return $options; +} + + +/** + * Sanitization function for mgjp_mv_ir settings + * + * @since 0.8 + * + * @param $input array of options from settings page + * @return array sanitized array of mgjp_mv_ir options + */ +function mgjp_mv_ir_sanitize( $input ) { + + $options = get_option( 'mgjp_mv_ir' ); + + $options['is_on'] = isset( $input['is_on'] ) ? ! ! $input['is_on'] : false; + + if ( isset( $input['id'] ) && wp_attachment_is_image( absint( $input['id'] ) ) ) + $options['id'] = absint( $input['id'] ); + else + add_settings_error( + 'mgjp_mv_ir', + 'invalid-attachment-id', + __( 'The Media Vault placeholder image ID must be the ID of an existing image attachment in your media library. Please select a different Media Vault placeholder image.', 'media-vault' ) + ); + + if ( isset( $input['default'] ) && wp_attachment_is_image( absint( $input['default'] ) ) ) + $options['default'] = absint( $input['default'] ); + + return $options; +} + + +/** + * Render the General Settings info txt + * + * @since 0.4 + */ +function mgjp_mv_render_general_settings_info_txt() { + + echo '

Media Vault

'; + echo '

'; + esc_html_e( 'Media Vault is a plugin that allows you to protect media files in your uploads folder.', 'media-vault' ); + echo ' '; + esc_html_e( 'Here you can set options for:', 'media-vault' ); + echo '

'; + +} + + +/** + * Render a generic single checkbox field, supports options + * saved in an array *for options saved in an array remember + * to always manually handle sanitizing the saved settings + * + * @since 0.8 + * + * @param array Array of arguments passed the specific settings field + */ +function mgjp_mv_render_checkbox_field( $args ) { + + $id = isset( $args['label_for'] ) ? $args['label_for'] : ( isset( $args['id'] ) ? $args['id'] : '' ); + $id = esc_attr( $id ); + + $option = get_option( $args['option'] ); + $name = $args['option']; + if ( isset( $args['option_id'] ) ) { + $option = isset( $option[$args['option_id']] ) ? $option[$args['option_id']] : null; + $name = $args['option'] . '[' . $args['option_id'] . ']'; + } + + $value = isset( $args['value'] ) ? $args['value'] : true; + + ?> + + + + + + + + + + + __( 'Media Vault selected placeholder image', 'media-vault' ), + 'title' => __( 'Selected placeholder', 'media-vault' ) + ); + + wp_localize_script( 'mgjp-image-selector', 'mgjp_mv_options_media', array( + 'ir_select_btn' => __( 'Select Placeholder', 'media-vault' ), + 'ir_select_btn2' => __( 'Change Placeholder', 'media-vault' ), + 'ir_restore_btn' => __( 'Restore the Default', 'media-vault' ), + 'ir_modal_title' => __( 'Select image placeholder for images that have been restricted.', 'media-vault' ), + 'ir_modal_btn' => __( 'Use image as placeholder', 'media-vault' ), + 'ir_image_args' => $image_args, + 'ir_default' => isset( $ir['default'] ) ? $ir['default'] : -1, + 'ir_size' => array( 100, 80 ), + 'ir_restore_nonce' => wp_create_nonce( 'mgjp_mv_ir_restore_default' ) + ) ); + + ?> + + + +

+ + + +

+ +
+ +
+ + + + + + + +
+ +
+ + + +
+ +
+ + base ) + return; + + wp_enqueue_media(); + wp_enqueue_script( 'mgjp-image-selector', plugins_url( 'js/min/mv-image-selector.min.js', __FILE__ ), array( 'jquery', 'json2' ), null, true ); + +} +add_action( 'admin_enqueue_scripts', 'mgjp_mv_options_media_enqueue_scripts' ); + +?> \ No newline at end of file diff --git a/mv-shortcodes.php b/mv-shortcodes.php new file mode 100644 index 0000000..a2c072c --- /dev/null +++ b/mv-shortcodes.php @@ -0,0 +1,88 @@ + + * @license GPL-3.0+ + */ + + +/** + * Add shortcode handler to print download link(s) for files + * in the wp uploads folder + * + * @since 0.5 + * + * @param $atts array Array of parameters passed to the shortcode through the editor + * acceptable parameters include: + * 'ids' int || string list of attachment ids (int), comma separated + * 'sizes' string list of desired file sizes per id if attachment type is image, comma separated + * 'thumb' bool true if thumb is desired in link list + * 'thumb_size' string desired size the thumb should display as + */ +function mgjp_mv_download_links_list_shortcode_handler( $atts ) { + + extract( shortcode_atts( array( + 'ids' => null, + 'sizes' => 'full', + 'thumb' => false, // Not implemented yet + 'thumb_size' => 'thumbnail' // Not implemented yet + ), $atts ) ); + + if ( empty( $ids ) ) + return; + + $ids = explode( ',', str_replace( ' ', '', $ids ) ); + $sizes = explode( ',', str_replace( ' ', '', $sizes ) ); + + foreach ( $ids as $key => $id ) { + + if ( ! absint( $id ) || ! mgjp_mv_check_user_permitted( $id ) ) + continue; + + $size = $sizes[0]; + if ( isset( $sizes[$key] ) ) + $size = $sizes[$key]; + + $file = mgjp_mv_get_attachment_download_url( $id, $size ); + if ( is_wp_error( $file ) ) + continue; + + $files[] = array( $id, $file ); + + } + + if ( ! isset( $files ) ) + return; + + ob_start(); + + if ( ! isset( $files[1] ) ) : ?> + + + + + + + + + + \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..ccb57a0 --- /dev/null +++ b/readme.txt @@ -0,0 +1,188 @@ +=== Media Vault === +Contributors: Max GJP +Donate Link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6KFT65LQXEHFQ +Tags: media, security, protection, attachments, downloads, download links, powerful, shortcode, flexible, simple, uploads, images, multisite, files, links, private, documents +Requires at least: 3.5.0 +Tested up to: 3.8.1 +Stable tag: 0.8.12 +License: GPLv3 or later +License URI: http://www.gnu.org/licenses/gpl-3.0.html + +Protect attachment files from direct access using powerful and flexible restrictions. Offer safe download links for any file in your uploads folder. + +== Description == + += Protected Attachment Files = + +Media Vault cordons off a section of your WordPress uploads folder and secures it, protecting all files within by passing requests for them through a *powerful, flexible and completely customizable* set of permission checks. + +After activating the plugin, to protect attachment files with Media Vault you can: + +* use the *Media Uploader admin page* to upload new protected attachments, +* use the *Media Vault metabox* to toggle file protection on the 'Edit Media' admin page, +* use the the *Media Vault Protection Settings* fields in the new Media Modal, or, +* using *bulk actions* in your Media Library page, you can change file protection on multiple pre-existing attachments at once. + +By default the only permission check that the plugin does on media files is that the user requesting them be logged in. You can change this *default* behavior from the 'Media Settings' page in the 'Settings' menu of the WordPress Admin. You can also change the restrictions set on attachments on an individual basis by means of either the Media Vault metabox on the 'Edit Media' page or the Media Vault Protection Settings fields in the new Media Modal. + +You can also write your own custom restrictions using the `mgjp_mv_add_permission()` function. See [this support question](http://wordpress.org/support/topic/restrict-only-for-subscribers?replies=5) for more details. + += Safe Download Links = + +Creating a cross-browser compatible download link for a file is a harder task than might be expected. Media Vault handles this for you, and it does so while preserving all the file security features discussed earlier like blocking downloads to people who should not have access to the file. + +The download links are available through a simple shortcode that you can use in your post/page editor screen: + + [mv_dl_links ids="1,2,3"] + +where 'ids' are the comma separated list of attachment ids you would like to make available for download in the list. + + +*Note:* Plugin comes with styles ready for WordPress 3.8+! + +*Note:* **Now supports WordPress MultiSite!** + +== Installation == + += Install Through your Blog's Admin = +*This sometimes does not to work on `localhost`, so if you're running your site off your own computer it's simpler to use the second method.* + +1. Go to the 'Plugins' menu in WordPress and select 'Add New'. +1. Type 'Media Vault' in the Search Box and press the 'Search' button. +1. When you find 'Media Vault', click 'Install Now' and after reading it, click 'ok' on the little alert that pops up. +1. When the plugin finishes installing, simply click 'Activate Now'. + += Downloading from WordPress.org = + +1. Clicking the big 'Download' button on the right on this page (wordpress.org/plugins/media-vault/) will download the plugin's `zip` folder (`mediavault.zip`). +1. Upload this `zip` folder to your server; to the `/wp-content/plugins/` directory of the site you wish to install the plugin on. +1. Extract the contents of the `zip`. Once it is done you can delete the `mediavault.zip` file if you wish. +1. Activate the plugin through the 'Plugins' menu in WordPress. + + +Once you have Media Vault activated and fully enabled don't forget to go and check out the plugin's settings on the 'Media Settings' page under the admin 'Settings' menu. + +== Frequently Asked Questions == + += How do I toggle File Protection on an existing Attachment? = + +You have two options. If you only want to toggle File Protection on **a single attachment**, you can do it directly from the attachment's Edit page. In the 'Media Vault Settings' metabox in the right column, you can toggle protection by clicking the button that will either say 'Add to Protected' or 'Remove from Protected'. Remember to click 'Update' to save the changes you have made. + +If you want to toggle File Protection on **multiple attachments**, the plugin comes with two bulk actions that can be performed in the Media Library page in the WordPress Admin. On the Media Library page select the attachment or attachments you would like to manipulate by ticking the box next to their title. Then from the 'bulk options' dropdown select either the 'Add to Protected' or 'Remove from Protected' option and click the 'Apply' button next to the dropdown. + +You can verify that the action took effect by looking at the Media Vault column in the Media Library list table. It will display when an attachment's files are protected as well as the permissions set on the particular attachment. + += Can files uploaded from the front-end be automatically protected? = + +Yes they can, see [this support question](http://wordpress.org/support/topic/default-upload-protection-from-front-end?replies=5) for more details! + += How are unprotected files handled? How does this plugin work? = + +This question was recently asked and answered in [this support thread](https://wordpress.org/support/topic/how-the-unprotected-files-are-handeled?replies=3), check it out! + +== Screenshots == + +1. The WordPress Media Upload page with Media Vault file protection activated. +2. An example of the access denied prompt produced by a custom file access restriction implemented very simply using Media Vault. +3. The WordPress Media Upload page with Media Vault file protection activated (in WP mp6 & WP 3.8+) + +== Changelog == + += 0.8.12 = +fixed bug in `mv-file-handler.php` causing php Notice and corrupted files. Big thanks to user [ikivanov](http://profiles.wordpress.org/ikivanov) for pointing it out and providing the solution! + += 0.8.11 = + +* fixed bug in `mv-metaboxes.php` causing php Notice. Thank you user [ikivanov](http://profiles.wordpress.org/ikivanov) for pointing it out! +* fixed bug in `mv-metaboxes.php` causing metabox stylesheet not to be served + += 0.8.10 = +Fixed typo causing php error in `mv-extra-activation-steps.php`. Thank you user [wwn2013](http://profiles.wordpress.org/wwn2013) for pointing it out! + += 0.8.9 = + +* Added Attachment Edit fields to the new Media Modal to make it easier to manage which files are protected with Media Vault and what permissions are set on each protected file. +* Fixed visual bug with IE8 and the general sibling selector not showing permissions in the Media Vault Metabox on the attachment edit admin page. +* Organized minified js code into seperate folder + += 0.8.8 = +fixed bug in `mv-file-handler.php` that allowed files to be viewed in the protected folder when 'Save uploads in year/month folders' was *not* selected. Thanks to [WayneHarris](http://profiles.wordpress.org/wayneharris) for pointing the issue out. + += 0.8.7 = +added a body class to the WP admin to let Media Vault know to use the new 3.8+ styles + += 0.8.6 = +fixed code that required php 5.4 and above, to be compatible with older versions of php + += 0.8.5 = + +* Now the plugin is not fully enabled if the rewrite rules are detected to not be fully functioning as required +* Added flag to indicate Media Vault can **only** be network activated on WordPress Multisite installs +* Added return to homepage link in standard access denied message on protected media +* Added Media Vault Activation/Deactivation Helper (MVADH) to support setups where Media Vault cannot automatically configure all components it needs to function, particularly the rewrite rules. Currently, MVADH supports single & multisite WordPress installs on Apache + mod_rewrite. Support for more server technologies coming soon. *MVADH not supporting a particular server technology **does not** mean Media Vault cannot work with that technology*, just that you may need to figure some of how to make the rewrite rules work by yourself. +* Added **much** better support for WP multisite: better activation support, better deactivation support, better uninstallation support, better rewrite rule support, better file-handling support, better plugin update support. +* Added MVADH rewrite rule support for ugly permalink setups +* Made some performance tweaks & minor bugfixing + += 0.8 = + +* added functionality to allow a place-holder image to replace a requested protected image. +* refactored permission resolving functions to be more thorough and efficient. +* modified `mgjp_mv_admin_check_user_permitted()` function to handle non admin checking and renamed it to `mgjp_mv_check_user_permitted()` to reflect this. +* added plugin update handling class to manage per update required changes fluidly. +* created an `uninstall.php` file and moved all settings removal actions there so that settings are now saved when a user only deactivates and does not remove the plugin. +* added a link to the Media Vault settings to the Plugins page. +* fixed bug with the Media Vault metabox not being able to set the default permission on the attachment. +* fixed bug with the `mgjp_mv_get_the_permission()` function returning the wrong permission. + += 0.7.1 = +The Metabox - added a Media Vault metabox to the attachment editor screen to manage protection meta + bugfixing on the bulk actions script + += 0.7 = +*Minor remastering of permission checking code to address protected attachment access from within the WordPress backend. Highly recommended to immediately update.* + +* Rewrote default permissions to return rather than using `wp_die` directly. They now MUST either return `true` upon determining the current user is permitted to access a particular attachment; or if access is denied: `false` or a [`WP_Error`](http://codex.wordpress.org/Class_Reference/WP_Error) object with an error message included. +* Added `mgjp_mv_admin_check_user_permitted()` function to use permission functions to change access to attachments while within the WP Admin. +* Hooked into the 'user_has_cap' and 'media_row_actions' filters to restrict what users could see and manipulate in the backend for the specific attachments they did not have the permission to access. +* Rewrote the custom permission checking function handling section of the file-handling script `mv-file-handler.php` to accommodate the changes to the way custom permission functions now return values. + += 0.6 = +Initial Release. + +== Upgrade Notice == + += 0.8.12 = +fixed bug in `mv-file-handler.php` causing php Notice and corrupted files. Big thanks to user [ikivanov](http://profiles.wordpress.org/ikivanov) for pointing it out and providing the solution! + += 0.8.11 = +fixed bug in `mv-metaboxes.php` causing php Notice. Thank you user [ikivanov](http://profiles.wordpress.org/ikivanov) for pointing it out! + += 0.8.10 = +fixed typo causing php error in `mv-extra-activation-steps.php`. Thank you user [wwn2013](http://profiles.wordpress.org/wwn2013) for pointing it out! + += 0.8.9 = +Added Attachment Edit Fields to the new Media Modal and fixed visual bug with IE8 + += 0.8.8 = +fixed bug in `mv-file-handler.php` that allowed files to be viewed in the protected folder when 'Save uploads in year/month folders' was *not* selected. Thanks to [WayneHarris](http://profiles.wordpress.org/wayneharris) for pointing the issue out. + += 0.8.7 = +added a body class to the WP admin to let Media Vault know to use the new 3.8+ styles + += 0.8.6 = +fixed code that required php 5.4 and above, to be compatible with older versions of php + += 0.8.5 = +The WPMU update - more organized code, now 90% more optimized to run fine both on single-site installs as well as multisite installs. + += 0.8 = +The Update update - good amount of bugfixing, and streamlining of code. Added a class to handle fluid plugin updates and some functions to allow for image placeholders to appear in the place of restricted images. + += 0.7.1 = +The Metabox - added a Media Vault metabox to the attachment editor screen to manage protection meta + bugfixing + += 0.7 = +Version 0.7 includes minor remastering of the permission checking code to address protected attachment access from within the WordPress backend. It is strongly recommended that you upgrade from version 0.6. + += 0.6 = +This is the original release version. \ No newline at end of file diff --git a/uninstall.php b/uninstall.php new file mode 100644 index 0000000..d4b5cf5 --- /dev/null +++ b/uninstall.php @@ -0,0 +1,81 @@ + + * @license GPL-3.0+ + */ + + +/** Make sure this file is not being called directly **/ +if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) || ! current_user_can( 'delete_plugins' ) ) { + header( 'Status: 403 Forbidden' ); + header( 'HTTP/1.1 403 Forbidden' ); + exit(); +} + + + +/** + * Media Vault internal Uninstall function for a single + * blog install or for each blog site + * in network activation mode + * + * @since 0.8.5 + */ +function _mgjp_mv_uninstall_local( $blog_id = 0 ) { + + // Delete the default Media Vault placeholder image if it + // still exists + $ir['default'] = get_option( 'mgjp_mv_ir' ); + if ( $ir['default'] && wp_attachment_is_image( $ir['default'] ) ) + wp_delete_attachment( $ir['default'], true ); + + // Delete all Media Vault local options from the local options table + delete_option( 'mgjp_mv_version' ); + delete_option( 'mgjp_mv_default_permission' ); + delete_option( 'mgjp_mv_options' ); + delete_option( 'mgjp_mv_ir' ); + + // Delete all Media Vault attachment metadata from the local postmeta table + delete_post_meta_by_key( '_mgjp_mv_permission' ); + delete_post_meta_by_key( 'mgjp_mv_meta' ); +} + + + +// Flush rewrite rules to remove all Media Vault rewrite rules from +// the site's .htaccess file +remove_filter( 'mod_rewrite_rules', 'mgjp_mv_add_plugin_rewrite_rules' ); +flush_rewrite_rules(); + + +// Delete all Media Vault network-wide options from the options table +delete_site_option( 'mgjp_mv_version' ); +delete_site_option( 'mgjp_mv_enabled' ); +delete_site_option( 'mgjp_mv_deactivation' ); + + +if ( ! is_multisite() ) { + + // run the uninstall function for the single site + _mgjp_mv_uninstall_local(); + +} else if ( ! wp_is_large_network() ) { + global $wpdb; + + $blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ); + + // run the uninstall function for each site in the network + foreach ( $blog_ids as $blog_id ) { + + switch_to_blog( $blog_id ); + _mgjp_mv_uninstall_local( $blog_id ); + restore_current_blog(); + + } +} \ No newline at end of file