From b3e2d62a40b6d491f9627237b8891133a4f3c782 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 2 Feb 2016 15:04:23 -0500 Subject: [PATCH 01/22] Move the Simple_Local_Avatars class into a separate include --- includes/class-simple-local-avatars.php | 502 ++++++++++++++++++++++++ simple-local-avatars.php | 501 +---------------------- 2 files changed, 504 insertions(+), 499 deletions(-) create mode 100644 includes/class-simple-local-avatars.php diff --git a/includes/class-simple-local-avatars.php b/includes/class-simple-local-avatars.php new file mode 100644 index 00000000..c6f50198 --- /dev/null +++ b/includes/class-simple-local-avatars.php @@ -0,0 +1,502 @@ +options = (array) get_option( 'simple_local_avatars' ); + $this->avatar_ratings = array( + 'G' => __('G — Suitable for all audiences'), + 'PG' => __('PG — Possibly offensive, usually for audiences 13 and above'), + 'R' => __('R — Intended for adult audiences above 17'), + 'X' => __('X — Even more mature than above') + ); + + // supplement remote avatars, but not if inside "local only" mode + if ( empty( $this->options['only'] ) ) + add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 5 ); + + add_action( 'admin_init', array( $this, 'admin_init' ) ); + + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + add_action( 'show_user_profile', array( $this, 'edit_user_profile' ) ); + add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) ); + + add_action( 'personal_options_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'admin_action_remove-simple-local-avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'wp_ajax_assign_simple_local_avatar_media', array( $this, 'ajax_assign_simple_local_avatar_media' ) ); + add_action( 'wp_ajax_remove_simple_local_avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); + + add_filter( 'avatar_defaults', array( $this, 'avatar_defaults' ) ); + } + + /** + * Retrieve the local avatar for a user who provided a user ID or email address. + * + * @param string $avatar Avatar return by original function + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternative text to use in image tag. Defaults to blank + * @return string tag for the user's avatar + */ + public function get_avatar( $avatar = '', $id_or_email, $size = 96, $default = '', $alt = '' ) { + if ( is_numeric( $id_or_email ) ) + $user_id = (int) $id_or_email; + elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) + $user_id = $user->ID; + elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) + $user_id = (int) $id_or_email->user_id; + + if ( empty( $user_id ) ) + return $avatar; + + // fetch local avatar from meta and make sure it's properly ste + $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); + if ( empty( $local_avatars['full'] ) ) + return $avatar; + + // check rating + $avatar_rating = get_user_meta( $user_id, 'simple_local_avatar_rating', true ); + if ( ! empty( $avatar_rating ) && 'G' != $avatar_rating && ( $site_rating = get_option( 'avatar_rating' ) ) ) { + $ratings = array_keys( $this->avatar_ratings ); + $site_rating_weight = array_search( $site_rating, $ratings ); + $avatar_rating_weight = array_search( $avatar_rating, $ratings ); + if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) + return $avatar; + } + + // handle "real" media + if ( ! empty( $local_avatars['media_id'] ) ) { + // has the media been deleted? + if ( ! $avatar_full_path = get_attached_file( $local_avatars['media_id'] ) ) { + // only allowed logged in users to delete bad data to mitigate performance issues + if ( is_user_logged_in() ) + $this->avatar_delete( $user_id ); + + return $avatar; + } + } + + $size = (int) $size; + + if ( empty( $alt ) ) + $alt = get_the_author_meta( 'display_name', $user_id ); + + // generate a new size + if ( ! array_key_exists( $size, $local_avatars ) ) { + $local_avatars[$size] = $local_avatars['full']; // just in case of failure elsewhere + + // allow automatic rescaling to be turned off + if ( $allow_dynamic_resizing = apply_filters( 'simple_local_avatars_dynamic_resize', true ) ) : + + $upload_path = wp_upload_dir(); + + // get path for image by converting URL, unless its already been set, thanks to using media library approach + if ( ! isset( $avatar_full_path ) ) + $avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] ); + + // generate the new size + $editor = wp_get_image_editor( $avatar_full_path ); + if ( ! is_wp_error( $editor ) ) { + $resized = $editor->resize( $size, $size, true ); + if ( ! is_wp_error( $resized ) ) { + $dest_file = $editor->generate_filename(); + $saved = $editor->save( $dest_file ); + if ( ! is_wp_error( $saved ) ) + $local_avatars[$size] = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $dest_file ); + } + } + + // save updated avatar sizes + update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); + + endif; + } + + if ( 'http' != substr( $local_avatars[$size], 0, 4 ) ) + $local_avatars[$size] = home_url( $local_avatars[$size] ); + + $author_class = is_author( $user_id ) ? ' current-author' : '' ; + $avatar = "" . esc_attr( $alt ) . ""; + + return apply_filters( 'simple_local_avatar', $avatar ); + } + + public function admin_init() { + // upgrade pre 2.0 option + if ( $old_ops = get_option( 'simple_local_avatars_caps' ) ) { + if ( ! empty( $old_ops['simple_local_avatars_caps'] ) ) + update_option( 'simple_local_avatars', array( 'caps' => 1 ) ); + + delete_option( 'simple_local_avatar_caps' ); + } + + register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); + add_settings_field( 'simple-local-avatars-only', __('Local Avatars Only','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'only', 'desc' => 'Only allow local avatars (still uses Gravatar for default avatars)' ) ); + add_settings_field( 'simple-local-avatars-caps', __('Local Upload Permissions','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'caps', 'desc' => 'Only allow users with file upload capabilities to upload local avatars (Authors and above)' ) ); + } + + /** + * Add scripts to the profile editing page + * + * @param string $hook_suffix Page hook + */ + public function admin_enqueue_scripts( $hook_suffix ) { + if ( 'profile.php' != $hook_suffix && 'user-edit.php' != $hook_suffix ) + return; + + if ( current_user_can( 'upload_files' ) ) + wp_enqueue_media(); + + $user_id = ( 'profile.php' == $hook_suffix ) ? get_current_user_id() : (int) $_GET['user_id']; + + $this->remove_nonce = wp_create_nonce( 'remove_simple_local_avatar_nonce' ); + + $script_name_append = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; + wp_enqueue_script( 'simple-local-avatars', plugins_url( '', __FILE__ ) . '/simple-local-avatars' . $script_name_append . '.js', array('jquery'), false, true ); + wp_localize_script( 'simple-local-avatars', 'i10n_SimpleLocalAvatars', array( + 'user_id' => $user_id, + 'insertMediaTitle' => __('Choose an Avatar','simple-local-avatars'), + 'insertIntoPost' => __('Set as avatar','simple-local-avatars'), + 'deleteNonce' => $this->remove_nonce, + 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), + ) ); + } + + /** + * Sanitize new settings field before saving + * + * @param array|string $input Passed input values to sanitize + * @return array|string Sanitized input fields + */ + public function sanitize_options( $input ) { + $new_input['caps'] = empty( $input['caps'] ) ? 0 : 1; + $new_input['only'] = empty( $input['only'] ) ? 0 : 1; + return $new_input; + } + + /** + * Settings field for avatar upload capabilities + * + * @param array $args Field arguments + */ + public function avatar_settings_field( $args ) { + $args = wp_parse_args( $args, array( + 'key' => '', + 'desc' => '', + ) ); + + if ( empty( $this->options[$args['key']] ) ) + $this->options[$args['key']] = 0; + + echo ' + + '; + } + + /** + * Output new Avatar fields to user editing / profile screen + * + * @param object $profileuser User object + */ + public function edit_user_profile( $profileuser ) { + ?> +

+ + + + + + + + + + + +
+ ID ); + remove_filter( 'pre_option_avatar_rating', '__return_null' ); + ?> + + options['caps'] ); + + if ( $upload_rights ) { + do_action( 'simple_local_avatar_notices' ); + wp_nonce_field( 'simple_local_avatar_nonce', '_simple_local_avatar_nonce', false ); + $remove_url = add_query_arg(array( + 'action' => 'remove-simple-local-avatar', + 'user_id' => $profileuser->ID, + '_wpnonce' => $this->remove_nonce, + ) ); + ?> +

+
+ + +

+

+   + simple_local_avatar ) ) echo ' style="display:none;"'; ?>> +

+ simple_local_avatar ) ) + echo '' . __('No local avatar is set. Set up your avatar at Gravatar.com.','simple-local-avatars') . ''; + else + echo '' . __('You do not have media management permissions. To change your local avatar, contact the blog administrator.','simple-local-avatars') . ''; + } + ?> +
+
simple_local_avatar ) ); ?>> + + simple_local_avatar_rating ) || ! array_key_exists( $profileuser->simple_local_avatar_rating, $this->avatar_ratings ) ) + $profileuser->simple_local_avatar_rating = 'G'; + + foreach ( $this->avatar_ratings as $key => $rating ) : + echo "\n\t
"; + endforeach; + ?> +

+
+ avatar_delete( $user_id ); // delete old images if successful + + $meta_value = array(); + + // set the new avatar + if ( is_int( $url_or_media_id ) ) { + $meta_value['media_id'] = $url_or_media_id; + $url_or_media_id = wp_get_attachment_url( $url_or_media_id ); + } + + $meta_value['full'] = $url_or_media_id; + + update_user_meta( $user_id, 'simple_local_avatar', $meta_value ); // save user information (overwriting old) + } + + /** + * Save any changes to the user profile + * + * @param int $user_id ID of user being updated + */ + public function edit_user_profile_update( $user_id ) { + // check nonces + if( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) + return; + + // check for uploaded files + if ( ! empty( $_FILES['simple-local-avatar']['name'] ) ) : + + // need to be more secure since low privelege users can upload + if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { + $this->avatar_upload_error = __('For security reasons, the extension ".php" cannot be in your file name.','simple-local-avatars'); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; + } + + // front end (theme my profile etc) support + if ( ! function_exists( 'wp_handle_upload' ) ) + require_once( ABSPATH . 'wp-admin/includes/file.php' ); + + // allow developers to override file size upload limit for avatars + add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function + $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( + 'mimes' => array( + 'jpg|jpeg|jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + ), + 'test_form' => false, + 'unique_filename_callback' => array( $this, 'unique_filename_callback' ) + ) ); + + remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + if ( empty($avatar['file']) ) { // handle failures + switch ( $avatar['error'] ) { + case 'File type does not meet security guidelines. Try another.' : + $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); + break; + default : + $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); + } + + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + + return; + } + + $this->assign_new_user_avatar( $avatar['url'], $user_id ); + + endif; + + // handle rating + if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { + if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) + $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); + + update_user_meta( $user_id, 'simple_local_avatar_rating', $_POST['simple_local_avatar_rating'] ); + } + } + + /** + * Allow developers to override the maximum allowable file size for avatar uploads + * + * @param int $bytes WordPress default byte size check + * @return int Maximum byte size + */ + public function upload_size_limit( $bytes ) { + return apply_filters( 'simple_local_avatars_upload_limit', $bytes ); + } + + /** + * Runs when a user clicks the Remove button for the avatar + */ + public function action_remove_simple_local_avatar() { + if ( ! empty( $_GET['user_id'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'remove_simple_local_avatar_nonce' ) ) { + $user_id = (int) $_GET['user_id']; + + if ( ! current_user_can('edit_user', $user_id) ) + wp_die( __('You do not have permission to edit this user.') ); + + $this->avatar_delete( $user_id ); // delete old images if successful + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + echo get_simple_local_avatar( $user_id ); + } + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + die; + } + + /** + * AJAX callback for assigning media ID fetched from media library to user + */ + public function ajax_assign_simple_local_avatar_media() { + // check required information and permissions + if ( empty( $_POST['user_id'] ) || empty( $_POST['media_id'] ) || ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_user', $_POST['user_id'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'assign_simple_local_avatar_nonce' ) ) + die; + + $media_id = (int) $_POST['media_id']; + $user_id = (int) $_POST['user_id']; + + // ensure the media is real is an image + if ( wp_attachment_is_image( $media_id ) ) + $this->assign_new_user_avatar( $media_id, $user_id ); + + echo get_simple_local_avatar( $user_id ); + + die; + } + + /** + * remove the custom get_avatar hook for the default avatar list output on options-discussion.php + */ + public function avatar_defaults( $avatar_defaults ) { + remove_action( 'get_avatar', array( $this, 'get_avatar' ) ); + return $avatar_defaults; + } + + /** + * Delete avatars based on a user_id + * + * @param int $user_id + */ + public function avatar_delete( $user_id ) { + $old_avatars = (array) get_user_meta( $user_id, 'simple_local_avatar', true ); + + if ( empty( $old_avatars ) ) + return; + + // if it was uploaded media, don't erase the full size or try to erase an the ID + if ( array_key_exists( 'media_id', $old_avatars ) ) + unset( $old_avatars['media_id'], $old_avatars['full'] ); + + if ( ! empty( $old_avatars ) ) { + $upload_path = wp_upload_dir(); + + foreach ($old_avatars as $old_avatar ) { + // derive the path for the file based on the upload directory + $old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar ); + if ( file_exists( $old_avatar_path ) ) + unlink( $old_avatar_path ); + } + } + + delete_user_meta( $user_id, 'simple_local_avatar' ); + delete_user_meta( $user_id, 'simple_local_avatar_rating' ); + } + + /** + * Creates a unique, meaningful file name for uploaded avatars. + * + * @param string $dir Path for file + * @param string $name Filename + * @param string $ext File extension (e.g. ".jpg") + * @return string Final filename + */ + public function unique_filename_callback( $dir, $name, $ext ) { + $user = get_user_by( 'id', (int) $this->user_id_being_edited ); + $name = $base_name = sanitize_file_name( $user->display_name . '_avatar_' . time() ); + + // ensure no conflicts with existing file names + $number = 1; + while ( file_exists( $dir . "/$name$ext" ) ) { + $name = $base_name . '_' . $number; + $number++; + } + + return $name . $ext; + } + + /** + * Adds errors based on avatar upload problems. + * + * @param WP_Error $errors Error messages for user profile screen. + */ + public function user_profile_update_errors( WP_Error $errors ) { + $errors->add( 'avatar_error', $this->avatar_upload_error ); + } +} diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 7904a756..d9e5cc14 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -9,510 +9,13 @@ License: GPLv2 or later */ -/** - * add field to user profiles - */ - -class Simple_Local_Avatars { - private $user_id_being_edited, $avatar_upload_error, $remove_nonce, $avatar_ratings; - public $options; - - /** - * Set up the hooks and default values - */ - public function __construct() { - load_plugin_textdomain( 'simple-local-avatars', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' ); - - $this->options = (array) get_option( 'simple_local_avatars' ); - $this->avatar_ratings = array( - 'G' => __('G — Suitable for all audiences'), - 'PG' => __('PG — Possibly offensive, usually for audiences 13 and above'), - 'R' => __('R — Intended for adult audiences above 17'), - 'X' => __('X — Even more mature than above') - ); - - // supplement remote avatars, but not if inside "local only" mode - if ( empty( $this->options['only'] ) ) - add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 5 ); - - add_action( 'admin_init', array( $this, 'admin_init' ) ); - - add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); - add_action( 'show_user_profile', array( $this, 'edit_user_profile' ) ); - add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) ); - - add_action( 'personal_options_update', array( $this, 'edit_user_profile_update' ) ); - add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) ); - add_action( 'admin_action_remove-simple-local-avatar', array( $this, 'action_remove_simple_local_avatar' ) ); - add_action( 'wp_ajax_assign_simple_local_avatar_media', array( $this, 'ajax_assign_simple_local_avatar_media' ) ); - add_action( 'wp_ajax_remove_simple_local_avatar', array( $this, 'action_remove_simple_local_avatar' ) ); - add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); - - add_filter( 'avatar_defaults', array( $this, 'avatar_defaults' ) ); - } - - /** - * Retrieve the local avatar for a user who provided a user ID or email address. - * - * @param string $avatar Avatar return by original function - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param string $alt Alternative text to use in image tag. Defaults to blank - * @return string tag for the user's avatar - */ - public function get_avatar( $avatar = '', $id_or_email, $size = 96, $default = '', $alt = '' ) { - if ( is_numeric( $id_or_email ) ) - $user_id = (int) $id_or_email; - elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) - $user_id = $user->ID; - elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) - $user_id = (int) $id_or_email->user_id; - - if ( empty( $user_id ) ) - return $avatar; - - // fetch local avatar from meta and make sure it's properly ste - $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); - if ( empty( $local_avatars['full'] ) ) - return $avatar; - - // check rating - $avatar_rating = get_user_meta( $user_id, 'simple_local_avatar_rating', true ); - if ( ! empty( $avatar_rating ) && 'G' != $avatar_rating && ( $site_rating = get_option( 'avatar_rating' ) ) ) { - $ratings = array_keys( $this->avatar_ratings ); - $site_rating_weight = array_search( $site_rating, $ratings ); - $avatar_rating_weight = array_search( $avatar_rating, $ratings ); - if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) - return $avatar; - } - - // handle "real" media - if ( ! empty( $local_avatars['media_id'] ) ) { - // has the media been deleted? - if ( ! $avatar_full_path = get_attached_file( $local_avatars['media_id'] ) ) { - // only allowed logged in users to delete bad data to mitigate performance issues - if ( is_user_logged_in() ) - $this->avatar_delete( $user_id ); - - return $avatar; - } - } - - $size = (int) $size; - - if ( empty( $alt ) ) - $alt = get_the_author_meta( 'display_name', $user_id ); - - // generate a new size - if ( ! array_key_exists( $size, $local_avatars ) ) { - $local_avatars[$size] = $local_avatars['full']; // just in case of failure elsewhere - - // allow automatic rescaling to be turned off - if ( $allow_dynamic_resizing = apply_filters( 'simple_local_avatars_dynamic_resize', true ) ) : - - $upload_path = wp_upload_dir(); - - // get path for image by converting URL, unless its already been set, thanks to using media library approach - if ( ! isset( $avatar_full_path ) ) - $avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] ); - - // generate the new size - $editor = wp_get_image_editor( $avatar_full_path ); - if ( ! is_wp_error( $editor ) ) { - $resized = $editor->resize( $size, $size, true ); - if ( ! is_wp_error( $resized ) ) { - $dest_file = $editor->generate_filename(); - $saved = $editor->save( $dest_file ); - if ( ! is_wp_error( $saved ) ) - $local_avatars[$size] = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $dest_file ); - } - } - - // save updated avatar sizes - update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); - - endif; - } - - if ( 'http' != substr( $local_avatars[$size], 0, 4 ) ) - $local_avatars[$size] = home_url( $local_avatars[$size] ); - - $author_class = is_author( $user_id ) ? ' current-author' : '' ; - $avatar = "" . esc_attr( $alt ) . ""; - - return apply_filters( 'simple_local_avatar', $avatar ); - } - - public function admin_init() { - // upgrade pre 2.0 option - if ( $old_ops = get_option( 'simple_local_avatars_caps' ) ) { - if ( ! empty( $old_ops['simple_local_avatars_caps'] ) ) - update_option( 'simple_local_avatars', array( 'caps' => 1 ) ); - - delete_option( 'simple_local_avatar_caps' ); - } - - register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); - add_settings_field( 'simple-local-avatars-only', __('Local Avatars Only','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'only', 'desc' => 'Only allow local avatars (still uses Gravatar for default avatars)' ) ); - add_settings_field( 'simple-local-avatars-caps', __('Local Upload Permissions','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'caps', 'desc' => 'Only allow users with file upload capabilities to upload local avatars (Authors and above)' ) ); - } - - /** - * Add scripts to the profile editing page - * - * @param string $hook_suffix Page hook - */ - public function admin_enqueue_scripts( $hook_suffix ) { - if ( 'profile.php' != $hook_suffix && 'user-edit.php' != $hook_suffix ) - return; - - if ( current_user_can( 'upload_files' ) ) - wp_enqueue_media(); - - $user_id = ( 'profile.php' == $hook_suffix ) ? get_current_user_id() : (int) $_GET['user_id']; - - $this->remove_nonce = wp_create_nonce( 'remove_simple_local_avatar_nonce' ); - - $script_name_append = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; - wp_enqueue_script( 'simple-local-avatars', plugins_url( '', __FILE__ ) . '/simple-local-avatars' . $script_name_append . '.js', array('jquery'), false, true ); - wp_localize_script( 'simple-local-avatars', 'i10n_SimpleLocalAvatars', array( - 'user_id' => $user_id, - 'insertMediaTitle' => __('Choose an Avatar','simple-local-avatars'), - 'insertIntoPost' => __('Set as avatar','simple-local-avatars'), - 'deleteNonce' => $this->remove_nonce, - 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), - ) ); - } - - /** - * Sanitize new settings field before saving - * - * @param array|string $input Passed input values to sanitize - * @return array|string Sanitized input fields - */ - public function sanitize_options( $input ) { - $new_input['caps'] = empty( $input['caps'] ) ? 0 : 1; - $new_input['only'] = empty( $input['only'] ) ? 0 : 1; - return $new_input; - } - - /** - * Settings field for avatar upload capabilities - * - * @param array $args Field arguments - */ - public function avatar_settings_field( $args ) { - $args = wp_parse_args( $args, array( - 'key' => '', - 'desc' => '', - ) ); - - if ( empty( $this->options[$args['key']] ) ) - $this->options[$args['key']] = 0; - - echo ' - - '; - } - - /** - * Output new Avatar fields to user editing / profile screen - * - * @param object $profileuser User object - */ - public function edit_user_profile( $profileuser ) { - ?> -

- - - - - - - - - - - -
- ID ); - remove_filter( 'pre_option_avatar_rating', '__return_null' ); - ?> - - options['caps'] ); - - if ( $upload_rights ) { - do_action( 'simple_local_avatar_notices' ); - wp_nonce_field( 'simple_local_avatar_nonce', '_simple_local_avatar_nonce', false ); - $remove_url = add_query_arg(array( - 'action' => 'remove-simple-local-avatar', - 'user_id' => $profileuser->ID, - '_wpnonce' => $this->remove_nonce, - ) ); - ?> -

-
- - -

-

-   - simple_local_avatar ) ) echo ' style="display:none;"'; ?>> -

- simple_local_avatar ) ) - echo '' . __('No local avatar is set. Set up your avatar at Gravatar.com.','simple-local-avatars') . ''; - else - echo '' . __('You do not have media management permissions. To change your local avatar, contact the blog administrator.','simple-local-avatars') . ''; - } - ?> -
-
simple_local_avatar ) ); ?>> - - simple_local_avatar_rating ) || ! array_key_exists( $profileuser->simple_local_avatar_rating, $this->avatar_ratings ) ) - $profileuser->simple_local_avatar_rating = 'G'; - - foreach ( $this->avatar_ratings as $key => $rating ) : - echo "\n\t
"; - endforeach; - ?> -

-
- avatar_delete( $user_id ); // delete old images if successful - - $meta_value = array(); - - // set the new avatar - if ( is_int( $url_or_media_id ) ) { - $meta_value['media_id'] = $url_or_media_id; - $url_or_media_id = wp_get_attachment_url( $url_or_media_id ); - } - - $meta_value['full'] = $url_or_media_id; - - update_user_meta( $user_id, 'simple_local_avatar', $meta_value ); // save user information (overwriting old) - } - - /** - * Save any changes to the user profile - * - * @param int $user_id ID of user being updated - */ - public function edit_user_profile_update( $user_id ) { - // check nonces - if( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) - return; - - // check for uploaded files - if ( ! empty( $_FILES['simple-local-avatar']['name'] ) ) : - - // need to be more secure since low privelege users can upload - if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { - $this->avatar_upload_error = __('For security reasons, the extension ".php" cannot be in your file name.','simple-local-avatars'); - add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); - return; - } - - // front end (theme my profile etc) support - if ( ! function_exists( 'wp_handle_upload' ) ) - require_once( ABSPATH . 'wp-admin/includes/file.php' ); - - // allow developers to override file size upload limit for avatars - add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); - - $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function - $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( - 'mimes' => array( - 'jpg|jpeg|jpe' => 'image/jpeg', - 'gif' => 'image/gif', - 'png' => 'image/png', - ), - 'test_form' => false, - 'unique_filename_callback' => array( $this, 'unique_filename_callback' ) - ) ); - - remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); - - if ( empty($avatar['file']) ) { // handle failures - switch ( $avatar['error'] ) { - case 'File type does not meet security guidelines. Try another.' : - $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); - break; - default : - $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); - } - - add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); - - return; - } - - $this->assign_new_user_avatar( $avatar['url'], $user_id ); - - endif; - - // handle rating - if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { - if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) - $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); - - update_user_meta( $user_id, 'simple_local_avatar_rating', $_POST['simple_local_avatar_rating'] ); - } - } - - /** - * Allow developers to override the maximum allowable file size for avatar uploads - * - * @param int $bytes WordPress default byte size check - * @return int Maximum byte size - */ - public function upload_size_limit( $bytes ) { - return apply_filters( 'simple_local_avatars_upload_limit', $bytes ); - } - - /** - * Runs when a user clicks the Remove button for the avatar - */ - public function action_remove_simple_local_avatar() { - if ( ! empty( $_GET['user_id'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'remove_simple_local_avatar_nonce' ) ) { - $user_id = (int) $_GET['user_id']; - - if ( ! current_user_can('edit_user', $user_id) ) - wp_die( __('You do not have permission to edit this user.') ); - - $this->avatar_delete( $user_id ); // delete old images if successful - - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) - echo get_simple_local_avatar( $user_id ); - } - - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) - die; - } - - /** - * AJAX callback for assigning media ID fetched from media library to user - */ - public function ajax_assign_simple_local_avatar_media() { - // check required information and permissions - if ( empty( $_POST['user_id'] ) || empty( $_POST['media_id'] ) || ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_user', $_POST['user_id'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'assign_simple_local_avatar_nonce' ) ) - die; - - $media_id = (int) $_POST['media_id']; - $user_id = (int) $_POST['user_id']; - - // ensure the media is real is an image - if ( wp_attachment_is_image( $media_id ) ) - $this->assign_new_user_avatar( $media_id, $user_id ); - - echo get_simple_local_avatar( $user_id ); - - die; - } - - /** - * remove the custom get_avatar hook for the default avatar list output on options-discussion.php - */ - public function avatar_defaults( $avatar_defaults ) { - remove_action( 'get_avatar', array( $this, 'get_avatar' ) ); - return $avatar_defaults; - } - - /** - * Delete avatars based on a user_id - * - * @param int $user_id - */ - public function avatar_delete( $user_id ) { - $old_avatars = (array) get_user_meta( $user_id, 'simple_local_avatar', true ); - - if ( empty( $old_avatars ) ) - return; - - // if it was uploaded media, don't erase the full size or try to erase an the ID - if ( array_key_exists( 'media_id', $old_avatars ) ) - unset( $old_avatars['media_id'], $old_avatars['full'] ); - - if ( ! empty( $old_avatars ) ) { - $upload_path = wp_upload_dir(); - - foreach ($old_avatars as $old_avatar ) { - // derive the path for the file based on the upload directory - $old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar ); - if ( file_exists( $old_avatar_path ) ) - unlink( $old_avatar_path ); - } - } - - delete_user_meta( $user_id, 'simple_local_avatar' ); - delete_user_meta( $user_id, 'simple_local_avatar_rating' ); - } - - /** - * Creates a unique, meaningful file name for uploaded avatars. - * - * @param string $dir Path for file - * @param string $name Filename - * @param string $ext File extension (e.g. ".jpg") - * @return string Final filename - */ - public function unique_filename_callback( $dir, $name, $ext ) { - $user = get_user_by( 'id', (int) $this->user_id_being_edited ); - $name = $base_name = sanitize_file_name( $user->display_name . '_avatar_' . time() ); - - // ensure no conflicts with existing file names - $number = 1; - while ( file_exists( $dir . "/$name$ext" ) ) { - $name = $base_name . '_' . $number; - $number++; - } - - return $name . $ext; - } - - /** - * Adds errors based on avatar upload problems. - * - * @param WP_Error $errors Error messages for user profile screen. - */ - public function user_profile_update_errors( WP_Error $errors ) { - $errors->add( 'avatar_error', $this->avatar_upload_error ); - } -} +require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php'; $simple_local_avatars = new Simple_Local_Avatars; /** * more efficient to call simple local avatar directly in theme and avoid gravatar setup - * + * * @param int|string|object $id_or_email A user ID, email address, or comment object * @param int $size Size of the avatar image * @param string $default URL to a default image to use if no avatar is available From 5b708e463ace5c20e972b094a9d4723577e6c095 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 2 Feb 2016 15:05:47 -0500 Subject: [PATCH 02/22] Move the template tags into a separate include file for better organization --- includes/template-tags.php | 81 ++++++++++++++++++++++++++++++++++++++ simple-local-avatars.php | 75 +---------------------------------- 2 files changed, 82 insertions(+), 74 deletions(-) create mode 100644 includes/template-tags.php diff --git a/includes/template-tags.php b/includes/template-tags.php new file mode 100644 index 00000000..521a9180 --- /dev/null +++ b/includes/template-tags.php @@ -0,0 +1,81 @@ + tag for the user's avatar + */ +function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { + global $simple_local_avatars; + $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ); + + if ( empty ( $avatar ) ) { + remove_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); + $avatar = get_avatar( $id_or_email, $size, $default, $alt ); + add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); + } + + return $avatar; +} + +if ( ! function_exists( 'get_avatar' ) && ( $simple_local_avatars_options = get_option('simple_local_avatars') ) && ! empty( $simple_local_avatars_options['only'] ) ) : + + /** + * Retrieve the avatar for a user who provided a user ID or email address. + * + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternative text to use in image tag. Defaults to blank + * @return string tag for the user's avatar + */ + function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { + global $simple_local_avatars; + + if ( ! get_option('show_avatars') ) + return false; + + $safe_alt = empty( $alt ) ? '' : esc_attr( $alt ); + + if ( !is_numeric($size) ) + $size = 96; + + if ( ! $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ) ) : + + if ( empty($default) ) { + $avatar_default = get_option('avatar_default'); + if ( empty($avatar_default) ) + $default = 'mystery'; + else + $default = $avatar_default; + } + + $host = is_ssl() ? 'https://secure.gravatar.com' : 'http://0.gravatar.com'; + + if ( 'mystery' == $default ) + $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com') + elseif ( 'blank' == $default ) + $default = includes_url( 'images/blank.gif' ); + elseif ( 'gravatar_default' == $default ) + $default = "$host/avatar/?s={$size}"; + else + $default = "$host/avatar/?d=$default&s={$size}"; + + $avatar = "{$safe_alt}"; + + endif; + + return apply_filters('get_avatar', $avatar, $id_or_email, $size, $default, $alt); + } + +endif; \ No newline at end of file diff --git a/simple-local-avatars.php b/simple-local-avatars.php index d9e5cc14..4fe65b01 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -10,83 +10,10 @@ */ require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php'; +require_once dirname( __FILE__ ) . '/includes/template-tags.php'; $simple_local_avatars = new Simple_Local_Avatars; -/** - * more efficient to call simple local avatar directly in theme and avoid gravatar setup - * - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param string $alt Alternate text to use in image tag. Defaults to blank - * @return string tag for the user's avatar - */ -function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { - global $simple_local_avatars; - $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ); - - if ( empty ( $avatar ) ) { - remove_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); - $avatar = get_avatar( $id_or_email, $size, $default, $alt ); - add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); - } - - return $avatar; -} - -if ( ! function_exists( 'get_avatar' ) && ( $simple_local_avatars_options = get_option('simple_local_avatars') ) && ! empty( $simple_local_avatars_options['only'] ) ) : - - /** - * Retrieve the avatar for a user who provided a user ID or email address. - * - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param string $alt Alternative text to use in image tag. Defaults to blank - * @return string tag for the user's avatar - */ - function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { - global $simple_local_avatars; - - if ( ! get_option('show_avatars') ) - return false; - - $safe_alt = empty( $alt ) ? '' : esc_attr( $alt ); - - if ( !is_numeric($size) ) - $size = 96; - - if ( ! $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ) ) : - - if ( empty($default) ) { - $avatar_default = get_option('avatar_default'); - if ( empty($avatar_default) ) - $default = 'mystery'; - else - $default = $avatar_default; - } - - $host = is_ssl() ? 'https://secure.gravatar.com' : 'http://0.gravatar.com'; - - if ( 'mystery' == $default ) - $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com') - elseif ( 'blank' == $default ) - $default = includes_url( 'images/blank.gif' ); - elseif ( 'gravatar_default' == $default ) - $default = "$host/avatar/?s={$size}"; - else - $default = "$host/avatar/?d=$default&s={$size}"; - - $avatar = "{$safe_alt}"; - - endif; - - return apply_filters('get_avatar', $avatar, $id_or_email, $size, $default, $alt); - } - -endif; - /** * on uninstallation, remove the custom field from the users and delete the local avatars */ From bcede6fef573d8821067964609d6b83dcce7c1d1 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 2 Feb 2016 15:10:15 -0500 Subject: [PATCH 03/22] Rewrite simple_local_avatars_uninstall() to adhere to the WordPress Coding Standards --- simple-local-avatars.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 4fe65b01..796a0ef2 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -15,21 +15,20 @@ $simple_local_avatars = new Simple_Local_Avatars; /** - * on uninstallation, remove the custom field from the users and delete the local avatars + * Upon installation, remove settings and local avatars from WordPress. */ - -register_uninstall_hook( __FILE__, 'simple_local_avatars_uninstall' ); - function simple_local_avatars_uninstall() { - $simple_local_avatars = new Simple_Local_Avatars; - $users = get_users(array( - 'meta_key' => 'simple_local_avatar', - 'fields' => 'ids', - )); + $instance = new Simple_Local_Avatars; + $users = get_users( array( + 'meta_key' => 'simple_local_avatar', + 'fields' => 'ids', + ) ); - foreach ( $users as $user_id ): - $simple_local_avatars->avatar_delete( $user_id ); - endforeach; - - delete_option('simple_local_avatars'); -} \ No newline at end of file + foreach ( $users as $user_id ) { + $instance->avatar_delete( $user_id ); + } + + // Remove settings from the database. + delete_option( 'simple_local_avatars' ); +} +register_uninstall_hook( __FILE__, 'simple_local_avatars_uninstall' ); From f7a67d7a307f9a716b5bba73cbd76bf61f2361ad Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 2 Feb 2016 15:12:24 -0500 Subject: [PATCH 04/22] Reformat the plugin header for readability and not blowing up syntax highlighters --- simple-local-avatars.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 796a0ef2..2d21a5e3 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -1,13 +1,16 @@ Date: Tue, 2 Feb 2016 15:28:06 -0500 Subject: [PATCH 05/22] Add a simple Contributing doc to the repo --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d15038b4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# Contributing to Simple Local Avatars + +Thank you for taking an interest in contributing towards the development of Simple Local Avatars! We welcome input and contributions from the community, so here are some guidelines to help you get started: + +## Git workflow + +First, be sure you're *creating new branches off of `develop`, which is the base branch for this repository; new code should only be merged into `master` when we're making a new release! + +For a full explanation of the Git workflow used in this project, please see [the 10up Engineering Best Practices](https://10up.github.io/Engineering-Best-Practices/version-control/#Plugins). + + +## Semantic versioning + +This plugin follows [semantic versioning](http://semver.org/), where releases correspond to MAJOR.MINOR.PATCH versions. For example, version 2.0.0 introduced several large changes, which impacted backwards compatibility. Were we to simply add a new feature, 2.1.0 would be the next version, and a small patch on that would produce 2.1.1. + +Any time there's a risk of a breaking change, the major version should be bumped and an appropriate Upgrade Notice added to the WordPress.org readme.txt file. From 420b079ac6504f7a841c60d20208496cd999b7ce Mon Sep 17 00:00:00 2001 From: Ravi Chandra Date: Wed, 1 Nov 2017 02:39:16 +0530 Subject: [PATCH 06/22] Fix `ArgumentCountError` due to `add_action` not specifying argument count --- simple-local-avatars.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 7904a756..79c63b5c 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -61,7 +61,7 @@ public function __construct() { * @param string $alt Alternative text to use in image tag. Defaults to blank * @return string tag for the user's avatar */ - public function get_avatar( $avatar = '', $id_or_email, $size = 96, $default = '', $alt = '' ) { + public function get_avatar( $avatar = '', $id_or_email = '', $size = 96, $default = '', $alt = '' ) { if ( is_numeric( $id_or_email ) ) $user_id = (int) $id_or_email; elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) @@ -526,7 +526,7 @@ function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt if ( empty ( $avatar ) ) { remove_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); $avatar = get_avatar( $id_or_email, $size, $default, $alt ); - add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); + add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ), 10, 5 ); } return $avatar; From 5553ee54c6dbf128d4352b1aec1a40d7713f61fa Mon Sep 17 00:00:00 2001 From: Eduard Florea Date: Thu, 16 Aug 2018 13:49:25 -0700 Subject: [PATCH 07/22] add composer.json file --- composer.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..aafa0610 --- /dev/null +++ b/composer.json @@ -0,0 +1,30 @@ +{ + "name": "10up/simple-local-avatars", + "description": "Adds an avatar upload field to user profiles. Generates requested sizes on demand just like Gravatar!", + "version": "2.0", + "type": "wordpress-plugin", + "keywords": [ + "wordpress", + "10up" + ], + "homepage": "https://github.com/10up/simple-local-avatars"", + "license": ["GPL-2.0-only"], + "authors": [ + { + "name": "10up", + "homepage": "https://10up.com/" + } + ], + "support": { + "issues": "https://github.com/10up/simple-local-avatars", + "source": "https://github.com/10up/simple-local-avatars" + }, + "require": { + "php": ">=5.3" + }, + "autoload": { + "files": [ + "simple-local-avatars.php" + ] + } +} \ No newline at end of file From 9b2482f38b03d1ca0e7702af771445312243fe46 Mon Sep 17 00:00:00 2001 From: Eduard Florea Date: Thu, 16 Aug 2018 15:14:17 -0700 Subject: [PATCH 08/22] fix extra double quote --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aafa0610..235a37c4 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "wordpress", "10up" ], - "homepage": "https://github.com/10up/simple-local-avatars"", + "homepage": "https://github.com/10up/simple-local-avatars", "license": ["GPL-2.0-only"], "authors": [ { From 3aba820b812d00705d6c98cb1fe4cc7ec9c5db6c Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Thu, 16 Aug 2018 22:30:29 -0400 Subject: [PATCH 09/22] Revert "Merge branch 'split-up-files' into develop" This reverts commit c856f6ade5cde1b718f8134fae1955cbed8681d4, reversing changes made to 4d70c3bd9ceda6a7e09532202d1a9d373d8b3743. --- CONTRIBUTING.md | 16 - includes/class-simple-local-avatars.php | 502 ------------------- includes/template-tags.php | 81 ---- simple-local-avatars.php | 616 +++++++++++++++++++++++- 4 files changed, 592 insertions(+), 623 deletions(-) delete mode 100644 CONTRIBUTING.md delete mode 100644 includes/class-simple-local-avatars.php delete mode 100644 includes/template-tags.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d15038b4..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,16 +0,0 @@ -# Contributing to Simple Local Avatars - -Thank you for taking an interest in contributing towards the development of Simple Local Avatars! We welcome input and contributions from the community, so here are some guidelines to help you get started: - -## Git workflow - -First, be sure you're *creating new branches off of `develop`, which is the base branch for this repository; new code should only be merged into `master` when we're making a new release! - -For a full explanation of the Git workflow used in this project, please see [the 10up Engineering Best Practices](https://10up.github.io/Engineering-Best-Practices/version-control/#Plugins). - - -## Semantic versioning - -This plugin follows [semantic versioning](http://semver.org/), where releases correspond to MAJOR.MINOR.PATCH versions. For example, version 2.0.0 introduced several large changes, which impacted backwards compatibility. Were we to simply add a new feature, 2.1.0 would be the next version, and a small patch on that would produce 2.1.1. - -Any time there's a risk of a breaking change, the major version should be bumped and an appropriate Upgrade Notice added to the WordPress.org readme.txt file. diff --git a/includes/class-simple-local-avatars.php b/includes/class-simple-local-avatars.php deleted file mode 100644 index c6f50198..00000000 --- a/includes/class-simple-local-avatars.php +++ /dev/null @@ -1,502 +0,0 @@ -options = (array) get_option( 'simple_local_avatars' ); - $this->avatar_ratings = array( - 'G' => __('G — Suitable for all audiences'), - 'PG' => __('PG — Possibly offensive, usually for audiences 13 and above'), - 'R' => __('R — Intended for adult audiences above 17'), - 'X' => __('X — Even more mature than above') - ); - - // supplement remote avatars, but not if inside "local only" mode - if ( empty( $this->options['only'] ) ) - add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 5 ); - - add_action( 'admin_init', array( $this, 'admin_init' ) ); - - add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); - add_action( 'show_user_profile', array( $this, 'edit_user_profile' ) ); - add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) ); - - add_action( 'personal_options_update', array( $this, 'edit_user_profile_update' ) ); - add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) ); - add_action( 'admin_action_remove-simple-local-avatar', array( $this, 'action_remove_simple_local_avatar' ) ); - add_action( 'wp_ajax_assign_simple_local_avatar_media', array( $this, 'ajax_assign_simple_local_avatar_media' ) ); - add_action( 'wp_ajax_remove_simple_local_avatar', array( $this, 'action_remove_simple_local_avatar' ) ); - add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); - - add_filter( 'avatar_defaults', array( $this, 'avatar_defaults' ) ); - } - - /** - * Retrieve the local avatar for a user who provided a user ID or email address. - * - * @param string $avatar Avatar return by original function - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param string $alt Alternative text to use in image tag. Defaults to blank - * @return string tag for the user's avatar - */ - public function get_avatar( $avatar = '', $id_or_email, $size = 96, $default = '', $alt = '' ) { - if ( is_numeric( $id_or_email ) ) - $user_id = (int) $id_or_email; - elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) - $user_id = $user->ID; - elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) - $user_id = (int) $id_or_email->user_id; - - if ( empty( $user_id ) ) - return $avatar; - - // fetch local avatar from meta and make sure it's properly ste - $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); - if ( empty( $local_avatars['full'] ) ) - return $avatar; - - // check rating - $avatar_rating = get_user_meta( $user_id, 'simple_local_avatar_rating', true ); - if ( ! empty( $avatar_rating ) && 'G' != $avatar_rating && ( $site_rating = get_option( 'avatar_rating' ) ) ) { - $ratings = array_keys( $this->avatar_ratings ); - $site_rating_weight = array_search( $site_rating, $ratings ); - $avatar_rating_weight = array_search( $avatar_rating, $ratings ); - if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) - return $avatar; - } - - // handle "real" media - if ( ! empty( $local_avatars['media_id'] ) ) { - // has the media been deleted? - if ( ! $avatar_full_path = get_attached_file( $local_avatars['media_id'] ) ) { - // only allowed logged in users to delete bad data to mitigate performance issues - if ( is_user_logged_in() ) - $this->avatar_delete( $user_id ); - - return $avatar; - } - } - - $size = (int) $size; - - if ( empty( $alt ) ) - $alt = get_the_author_meta( 'display_name', $user_id ); - - // generate a new size - if ( ! array_key_exists( $size, $local_avatars ) ) { - $local_avatars[$size] = $local_avatars['full']; // just in case of failure elsewhere - - // allow automatic rescaling to be turned off - if ( $allow_dynamic_resizing = apply_filters( 'simple_local_avatars_dynamic_resize', true ) ) : - - $upload_path = wp_upload_dir(); - - // get path for image by converting URL, unless its already been set, thanks to using media library approach - if ( ! isset( $avatar_full_path ) ) - $avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] ); - - // generate the new size - $editor = wp_get_image_editor( $avatar_full_path ); - if ( ! is_wp_error( $editor ) ) { - $resized = $editor->resize( $size, $size, true ); - if ( ! is_wp_error( $resized ) ) { - $dest_file = $editor->generate_filename(); - $saved = $editor->save( $dest_file ); - if ( ! is_wp_error( $saved ) ) - $local_avatars[$size] = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $dest_file ); - } - } - - // save updated avatar sizes - update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); - - endif; - } - - if ( 'http' != substr( $local_avatars[$size], 0, 4 ) ) - $local_avatars[$size] = home_url( $local_avatars[$size] ); - - $author_class = is_author( $user_id ) ? ' current-author' : '' ; - $avatar = "" . esc_attr( $alt ) . ""; - - return apply_filters( 'simple_local_avatar', $avatar ); - } - - public function admin_init() { - // upgrade pre 2.0 option - if ( $old_ops = get_option( 'simple_local_avatars_caps' ) ) { - if ( ! empty( $old_ops['simple_local_avatars_caps'] ) ) - update_option( 'simple_local_avatars', array( 'caps' => 1 ) ); - - delete_option( 'simple_local_avatar_caps' ); - } - - register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); - add_settings_field( 'simple-local-avatars-only', __('Local Avatars Only','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'only', 'desc' => 'Only allow local avatars (still uses Gravatar for default avatars)' ) ); - add_settings_field( 'simple-local-avatars-caps', __('Local Upload Permissions','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'caps', 'desc' => 'Only allow users with file upload capabilities to upload local avatars (Authors and above)' ) ); - } - - /** - * Add scripts to the profile editing page - * - * @param string $hook_suffix Page hook - */ - public function admin_enqueue_scripts( $hook_suffix ) { - if ( 'profile.php' != $hook_suffix && 'user-edit.php' != $hook_suffix ) - return; - - if ( current_user_can( 'upload_files' ) ) - wp_enqueue_media(); - - $user_id = ( 'profile.php' == $hook_suffix ) ? get_current_user_id() : (int) $_GET['user_id']; - - $this->remove_nonce = wp_create_nonce( 'remove_simple_local_avatar_nonce' ); - - $script_name_append = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; - wp_enqueue_script( 'simple-local-avatars', plugins_url( '', __FILE__ ) . '/simple-local-avatars' . $script_name_append . '.js', array('jquery'), false, true ); - wp_localize_script( 'simple-local-avatars', 'i10n_SimpleLocalAvatars', array( - 'user_id' => $user_id, - 'insertMediaTitle' => __('Choose an Avatar','simple-local-avatars'), - 'insertIntoPost' => __('Set as avatar','simple-local-avatars'), - 'deleteNonce' => $this->remove_nonce, - 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), - ) ); - } - - /** - * Sanitize new settings field before saving - * - * @param array|string $input Passed input values to sanitize - * @return array|string Sanitized input fields - */ - public function sanitize_options( $input ) { - $new_input['caps'] = empty( $input['caps'] ) ? 0 : 1; - $new_input['only'] = empty( $input['only'] ) ? 0 : 1; - return $new_input; - } - - /** - * Settings field for avatar upload capabilities - * - * @param array $args Field arguments - */ - public function avatar_settings_field( $args ) { - $args = wp_parse_args( $args, array( - 'key' => '', - 'desc' => '', - ) ); - - if ( empty( $this->options[$args['key']] ) ) - $this->options[$args['key']] = 0; - - echo ' - - '; - } - - /** - * Output new Avatar fields to user editing / profile screen - * - * @param object $profileuser User object - */ - public function edit_user_profile( $profileuser ) { - ?> -

- - - - - - - - - - - -
- ID ); - remove_filter( 'pre_option_avatar_rating', '__return_null' ); - ?> - - options['caps'] ); - - if ( $upload_rights ) { - do_action( 'simple_local_avatar_notices' ); - wp_nonce_field( 'simple_local_avatar_nonce', '_simple_local_avatar_nonce', false ); - $remove_url = add_query_arg(array( - 'action' => 'remove-simple-local-avatar', - 'user_id' => $profileuser->ID, - '_wpnonce' => $this->remove_nonce, - ) ); - ?> -

-
- - -

-

-   - simple_local_avatar ) ) echo ' style="display:none;"'; ?>> -

- simple_local_avatar ) ) - echo '' . __('No local avatar is set. Set up your avatar at Gravatar.com.','simple-local-avatars') . ''; - else - echo '' . __('You do not have media management permissions. To change your local avatar, contact the blog administrator.','simple-local-avatars') . ''; - } - ?> -
-
simple_local_avatar ) ); ?>> - - simple_local_avatar_rating ) || ! array_key_exists( $profileuser->simple_local_avatar_rating, $this->avatar_ratings ) ) - $profileuser->simple_local_avatar_rating = 'G'; - - foreach ( $this->avatar_ratings as $key => $rating ) : - echo "\n\t
"; - endforeach; - ?> -

-
- avatar_delete( $user_id ); // delete old images if successful - - $meta_value = array(); - - // set the new avatar - if ( is_int( $url_or_media_id ) ) { - $meta_value['media_id'] = $url_or_media_id; - $url_or_media_id = wp_get_attachment_url( $url_or_media_id ); - } - - $meta_value['full'] = $url_or_media_id; - - update_user_meta( $user_id, 'simple_local_avatar', $meta_value ); // save user information (overwriting old) - } - - /** - * Save any changes to the user profile - * - * @param int $user_id ID of user being updated - */ - public function edit_user_profile_update( $user_id ) { - // check nonces - if( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) - return; - - // check for uploaded files - if ( ! empty( $_FILES['simple-local-avatar']['name'] ) ) : - - // need to be more secure since low privelege users can upload - if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { - $this->avatar_upload_error = __('For security reasons, the extension ".php" cannot be in your file name.','simple-local-avatars'); - add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); - return; - } - - // front end (theme my profile etc) support - if ( ! function_exists( 'wp_handle_upload' ) ) - require_once( ABSPATH . 'wp-admin/includes/file.php' ); - - // allow developers to override file size upload limit for avatars - add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); - - $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function - $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( - 'mimes' => array( - 'jpg|jpeg|jpe' => 'image/jpeg', - 'gif' => 'image/gif', - 'png' => 'image/png', - ), - 'test_form' => false, - 'unique_filename_callback' => array( $this, 'unique_filename_callback' ) - ) ); - - remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); - - if ( empty($avatar['file']) ) { // handle failures - switch ( $avatar['error'] ) { - case 'File type does not meet security guidelines. Try another.' : - $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); - break; - default : - $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); - } - - add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); - - return; - } - - $this->assign_new_user_avatar( $avatar['url'], $user_id ); - - endif; - - // handle rating - if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { - if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) - $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); - - update_user_meta( $user_id, 'simple_local_avatar_rating', $_POST['simple_local_avatar_rating'] ); - } - } - - /** - * Allow developers to override the maximum allowable file size for avatar uploads - * - * @param int $bytes WordPress default byte size check - * @return int Maximum byte size - */ - public function upload_size_limit( $bytes ) { - return apply_filters( 'simple_local_avatars_upload_limit', $bytes ); - } - - /** - * Runs when a user clicks the Remove button for the avatar - */ - public function action_remove_simple_local_avatar() { - if ( ! empty( $_GET['user_id'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'remove_simple_local_avatar_nonce' ) ) { - $user_id = (int) $_GET['user_id']; - - if ( ! current_user_can('edit_user', $user_id) ) - wp_die( __('You do not have permission to edit this user.') ); - - $this->avatar_delete( $user_id ); // delete old images if successful - - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) - echo get_simple_local_avatar( $user_id ); - } - - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) - die; - } - - /** - * AJAX callback for assigning media ID fetched from media library to user - */ - public function ajax_assign_simple_local_avatar_media() { - // check required information and permissions - if ( empty( $_POST['user_id'] ) || empty( $_POST['media_id'] ) || ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_user', $_POST['user_id'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'assign_simple_local_avatar_nonce' ) ) - die; - - $media_id = (int) $_POST['media_id']; - $user_id = (int) $_POST['user_id']; - - // ensure the media is real is an image - if ( wp_attachment_is_image( $media_id ) ) - $this->assign_new_user_avatar( $media_id, $user_id ); - - echo get_simple_local_avatar( $user_id ); - - die; - } - - /** - * remove the custom get_avatar hook for the default avatar list output on options-discussion.php - */ - public function avatar_defaults( $avatar_defaults ) { - remove_action( 'get_avatar', array( $this, 'get_avatar' ) ); - return $avatar_defaults; - } - - /** - * Delete avatars based on a user_id - * - * @param int $user_id - */ - public function avatar_delete( $user_id ) { - $old_avatars = (array) get_user_meta( $user_id, 'simple_local_avatar', true ); - - if ( empty( $old_avatars ) ) - return; - - // if it was uploaded media, don't erase the full size or try to erase an the ID - if ( array_key_exists( 'media_id', $old_avatars ) ) - unset( $old_avatars['media_id'], $old_avatars['full'] ); - - if ( ! empty( $old_avatars ) ) { - $upload_path = wp_upload_dir(); - - foreach ($old_avatars as $old_avatar ) { - // derive the path for the file based on the upload directory - $old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar ); - if ( file_exists( $old_avatar_path ) ) - unlink( $old_avatar_path ); - } - } - - delete_user_meta( $user_id, 'simple_local_avatar' ); - delete_user_meta( $user_id, 'simple_local_avatar_rating' ); - } - - /** - * Creates a unique, meaningful file name for uploaded avatars. - * - * @param string $dir Path for file - * @param string $name Filename - * @param string $ext File extension (e.g. ".jpg") - * @return string Final filename - */ - public function unique_filename_callback( $dir, $name, $ext ) { - $user = get_user_by( 'id', (int) $this->user_id_being_edited ); - $name = $base_name = sanitize_file_name( $user->display_name . '_avatar_' . time() ); - - // ensure no conflicts with existing file names - $number = 1; - while ( file_exists( $dir . "/$name$ext" ) ) { - $name = $base_name . '_' . $number; - $number++; - } - - return $name . $ext; - } - - /** - * Adds errors based on avatar upload problems. - * - * @param WP_Error $errors Error messages for user profile screen. - */ - public function user_profile_update_errors( WP_Error $errors ) { - $errors->add( 'avatar_error', $this->avatar_upload_error ); - } -} diff --git a/includes/template-tags.php b/includes/template-tags.php deleted file mode 100644 index 521a9180..00000000 --- a/includes/template-tags.php +++ /dev/null @@ -1,81 +0,0 @@ - tag for the user's avatar - */ -function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { - global $simple_local_avatars; - $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ); - - if ( empty ( $avatar ) ) { - remove_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); - $avatar = get_avatar( $id_or_email, $size, $default, $alt ); - add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); - } - - return $avatar; -} - -if ( ! function_exists( 'get_avatar' ) && ( $simple_local_avatars_options = get_option('simple_local_avatars') ) && ! empty( $simple_local_avatars_options['only'] ) ) : - - /** - * Retrieve the avatar for a user who provided a user ID or email address. - * - * @param int|string|object $id_or_email A user ID, email address, or comment object - * @param int $size Size of the avatar image - * @param string $default URL to a default image to use if no avatar is available - * @param string $alt Alternative text to use in image tag. Defaults to blank - * @return string tag for the user's avatar - */ - function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { - global $simple_local_avatars; - - if ( ! get_option('show_avatars') ) - return false; - - $safe_alt = empty( $alt ) ? '' : esc_attr( $alt ); - - if ( !is_numeric($size) ) - $size = 96; - - if ( ! $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ) ) : - - if ( empty($default) ) { - $avatar_default = get_option('avatar_default'); - if ( empty($avatar_default) ) - $default = 'mystery'; - else - $default = $avatar_default; - } - - $host = is_ssl() ? 'https://secure.gravatar.com' : 'http://0.gravatar.com'; - - if ( 'mystery' == $default ) - $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com') - elseif ( 'blank' == $default ) - $default = includes_url( 'images/blank.gif' ); - elseif ( 'gravatar_default' == $default ) - $default = "$host/avatar/?s={$size}"; - else - $default = "$host/avatar/?d=$default&s={$size}"; - - $avatar = "{$safe_alt}"; - - endif; - - return apply_filters('get_avatar', $avatar, $id_or_email, $size, $default, $alt); - } - -endif; \ No newline at end of file diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 2d21a5e3..7904a756 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -1,37 +1,605 @@ options = (array) get_option( 'simple_local_avatars' ); + $this->avatar_ratings = array( + 'G' => __('G — Suitable for all audiences'), + 'PG' => __('PG — Possibly offensive, usually for audiences 13 and above'), + 'R' => __('R — Intended for adult audiences above 17'), + 'X' => __('X — Even more mature than above') + ); + + // supplement remote avatars, but not if inside "local only" mode + if ( empty( $this->options['only'] ) ) + add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 5 ); + + add_action( 'admin_init', array( $this, 'admin_init' ) ); + + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + add_action( 'show_user_profile', array( $this, 'edit_user_profile' ) ); + add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) ); + + add_action( 'personal_options_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'admin_action_remove-simple-local-avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'wp_ajax_assign_simple_local_avatar_media', array( $this, 'ajax_assign_simple_local_avatar_media' ) ); + add_action( 'wp_ajax_remove_simple_local_avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); + + add_filter( 'avatar_defaults', array( $this, 'avatar_defaults' ) ); + } + + /** + * Retrieve the local avatar for a user who provided a user ID or email address. + * + * @param string $avatar Avatar return by original function + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternative text to use in image tag. Defaults to blank + * @return string tag for the user's avatar + */ + public function get_avatar( $avatar = '', $id_or_email, $size = 96, $default = '', $alt = '' ) { + if ( is_numeric( $id_or_email ) ) + $user_id = (int) $id_or_email; + elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) + $user_id = $user->ID; + elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) + $user_id = (int) $id_or_email->user_id; + + if ( empty( $user_id ) ) + return $avatar; + + // fetch local avatar from meta and make sure it's properly ste + $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); + if ( empty( $local_avatars['full'] ) ) + return $avatar; + + // check rating + $avatar_rating = get_user_meta( $user_id, 'simple_local_avatar_rating', true ); + if ( ! empty( $avatar_rating ) && 'G' != $avatar_rating && ( $site_rating = get_option( 'avatar_rating' ) ) ) { + $ratings = array_keys( $this->avatar_ratings ); + $site_rating_weight = array_search( $site_rating, $ratings ); + $avatar_rating_weight = array_search( $avatar_rating, $ratings ); + if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) + return $avatar; + } + + // handle "real" media + if ( ! empty( $local_avatars['media_id'] ) ) { + // has the media been deleted? + if ( ! $avatar_full_path = get_attached_file( $local_avatars['media_id'] ) ) { + // only allowed logged in users to delete bad data to mitigate performance issues + if ( is_user_logged_in() ) + $this->avatar_delete( $user_id ); + + return $avatar; + } + } + + $size = (int) $size; + + if ( empty( $alt ) ) + $alt = get_the_author_meta( 'display_name', $user_id ); + + // generate a new size + if ( ! array_key_exists( $size, $local_avatars ) ) { + $local_avatars[$size] = $local_avatars['full']; // just in case of failure elsewhere + + // allow automatic rescaling to be turned off + if ( $allow_dynamic_resizing = apply_filters( 'simple_local_avatars_dynamic_resize', true ) ) : + + $upload_path = wp_upload_dir(); + + // get path for image by converting URL, unless its already been set, thanks to using media library approach + if ( ! isset( $avatar_full_path ) ) + $avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] ); + + // generate the new size + $editor = wp_get_image_editor( $avatar_full_path ); + if ( ! is_wp_error( $editor ) ) { + $resized = $editor->resize( $size, $size, true ); + if ( ! is_wp_error( $resized ) ) { + $dest_file = $editor->generate_filename(); + $saved = $editor->save( $dest_file ); + if ( ! is_wp_error( $saved ) ) + $local_avatars[$size] = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $dest_file ); + } + } + + // save updated avatar sizes + update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); + + endif; + } + + if ( 'http' != substr( $local_avatars[$size], 0, 4 ) ) + $local_avatars[$size] = home_url( $local_avatars[$size] ); + + $author_class = is_author( $user_id ) ? ' current-author' : '' ; + $avatar = "" . esc_attr( $alt ) . ""; + + return apply_filters( 'simple_local_avatar', $avatar ); + } + + public function admin_init() { + // upgrade pre 2.0 option + if ( $old_ops = get_option( 'simple_local_avatars_caps' ) ) { + if ( ! empty( $old_ops['simple_local_avatars_caps'] ) ) + update_option( 'simple_local_avatars', array( 'caps' => 1 ) ); + + delete_option( 'simple_local_avatar_caps' ); + } + + register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); + add_settings_field( 'simple-local-avatars-only', __('Local Avatars Only','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'only', 'desc' => 'Only allow local avatars (still uses Gravatar for default avatars)' ) ); + add_settings_field( 'simple-local-avatars-caps', __('Local Upload Permissions','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'caps', 'desc' => 'Only allow users with file upload capabilities to upload local avatars (Authors and above)' ) ); + } + + /** + * Add scripts to the profile editing page + * + * @param string $hook_suffix Page hook + */ + public function admin_enqueue_scripts( $hook_suffix ) { + if ( 'profile.php' != $hook_suffix && 'user-edit.php' != $hook_suffix ) + return; + + if ( current_user_can( 'upload_files' ) ) + wp_enqueue_media(); + + $user_id = ( 'profile.php' == $hook_suffix ) ? get_current_user_id() : (int) $_GET['user_id']; + + $this->remove_nonce = wp_create_nonce( 'remove_simple_local_avatar_nonce' ); + + $script_name_append = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; + wp_enqueue_script( 'simple-local-avatars', plugins_url( '', __FILE__ ) . '/simple-local-avatars' . $script_name_append . '.js', array('jquery'), false, true ); + wp_localize_script( 'simple-local-avatars', 'i10n_SimpleLocalAvatars', array( + 'user_id' => $user_id, + 'insertMediaTitle' => __('Choose an Avatar','simple-local-avatars'), + 'insertIntoPost' => __('Set as avatar','simple-local-avatars'), + 'deleteNonce' => $this->remove_nonce, + 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), + ) ); + } + + /** + * Sanitize new settings field before saving + * + * @param array|string $input Passed input values to sanitize + * @return array|string Sanitized input fields + */ + public function sanitize_options( $input ) { + $new_input['caps'] = empty( $input['caps'] ) ? 0 : 1; + $new_input['only'] = empty( $input['only'] ) ? 0 : 1; + return $new_input; + } + + /** + * Settings field for avatar upload capabilities + * + * @param array $args Field arguments + */ + public function avatar_settings_field( $args ) { + $args = wp_parse_args( $args, array( + 'key' => '', + 'desc' => '', + ) ); + + if ( empty( $this->options[$args['key']] ) ) + $this->options[$args['key']] = 0; + + echo ' + + '; + } + + /** + * Output new Avatar fields to user editing / profile screen + * + * @param object $profileuser User object + */ + public function edit_user_profile( $profileuser ) { + ?> +

+ + + + + + + + + + + +
+ ID ); + remove_filter( 'pre_option_avatar_rating', '__return_null' ); + ?> + + options['caps'] ); + + if ( $upload_rights ) { + do_action( 'simple_local_avatar_notices' ); + wp_nonce_field( 'simple_local_avatar_nonce', '_simple_local_avatar_nonce', false ); + $remove_url = add_query_arg(array( + 'action' => 'remove-simple-local-avatar', + 'user_id' => $profileuser->ID, + '_wpnonce' => $this->remove_nonce, + ) ); + ?> +

+
+ + +

+

+   + simple_local_avatar ) ) echo ' style="display:none;"'; ?>> +

+ simple_local_avatar ) ) + echo '' . __('No local avatar is set. Set up your avatar at Gravatar.com.','simple-local-avatars') . ''; + else + echo '' . __('You do not have media management permissions. To change your local avatar, contact the blog administrator.','simple-local-avatars') . ''; + } + ?> +
+
simple_local_avatar ) ); ?>> + + simple_local_avatar_rating ) || ! array_key_exists( $profileuser->simple_local_avatar_rating, $this->avatar_ratings ) ) + $profileuser->simple_local_avatar_rating = 'G'; + + foreach ( $this->avatar_ratings as $key => $rating ) : + echo "\n\t
"; + endforeach; + ?> +

+
+ avatar_delete( $user_id ); // delete old images if successful + + $meta_value = array(); + + // set the new avatar + if ( is_int( $url_or_media_id ) ) { + $meta_value['media_id'] = $url_or_media_id; + $url_or_media_id = wp_get_attachment_url( $url_or_media_id ); + } + + $meta_value['full'] = $url_or_media_id; + + update_user_meta( $user_id, 'simple_local_avatar', $meta_value ); // save user information (overwriting old) + } + + /** + * Save any changes to the user profile + * + * @param int $user_id ID of user being updated + */ + public function edit_user_profile_update( $user_id ) { + // check nonces + if( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) + return; + + // check for uploaded files + if ( ! empty( $_FILES['simple-local-avatar']['name'] ) ) : + + // need to be more secure since low privelege users can upload + if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { + $this->avatar_upload_error = __('For security reasons, the extension ".php" cannot be in your file name.','simple-local-avatars'); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; + } + + // front end (theme my profile etc) support + if ( ! function_exists( 'wp_handle_upload' ) ) + require_once( ABSPATH . 'wp-admin/includes/file.php' ); + + // allow developers to override file size upload limit for avatars + add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function + $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( + 'mimes' => array( + 'jpg|jpeg|jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + ), + 'test_form' => false, + 'unique_filename_callback' => array( $this, 'unique_filename_callback' ) + ) ); + + remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + if ( empty($avatar['file']) ) { // handle failures + switch ( $avatar['error'] ) { + case 'File type does not meet security guidelines. Try another.' : + $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); + break; + default : + $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); + } + + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); -require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php'; -require_once dirname( __FILE__ ) . '/includes/template-tags.php'; + return; + } + + $this->assign_new_user_avatar( $avatar['url'], $user_id ); + + endif; + + // handle rating + if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { + if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) + $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); + + update_user_meta( $user_id, 'simple_local_avatar_rating', $_POST['simple_local_avatar_rating'] ); + } + } + + /** + * Allow developers to override the maximum allowable file size for avatar uploads + * + * @param int $bytes WordPress default byte size check + * @return int Maximum byte size + */ + public function upload_size_limit( $bytes ) { + return apply_filters( 'simple_local_avatars_upload_limit', $bytes ); + } + + /** + * Runs when a user clicks the Remove button for the avatar + */ + public function action_remove_simple_local_avatar() { + if ( ! empty( $_GET['user_id'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'remove_simple_local_avatar_nonce' ) ) { + $user_id = (int) $_GET['user_id']; + + if ( ! current_user_can('edit_user', $user_id) ) + wp_die( __('You do not have permission to edit this user.') ); + + $this->avatar_delete( $user_id ); // delete old images if successful + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + echo get_simple_local_avatar( $user_id ); + } + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + die; + } + + /** + * AJAX callback for assigning media ID fetched from media library to user + */ + public function ajax_assign_simple_local_avatar_media() { + // check required information and permissions + if ( empty( $_POST['user_id'] ) || empty( $_POST['media_id'] ) || ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_user', $_POST['user_id'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'assign_simple_local_avatar_nonce' ) ) + die; + + $media_id = (int) $_POST['media_id']; + $user_id = (int) $_POST['user_id']; + + // ensure the media is real is an image + if ( wp_attachment_is_image( $media_id ) ) + $this->assign_new_user_avatar( $media_id, $user_id ); + + echo get_simple_local_avatar( $user_id ); + + die; + } + + /** + * remove the custom get_avatar hook for the default avatar list output on options-discussion.php + */ + public function avatar_defaults( $avatar_defaults ) { + remove_action( 'get_avatar', array( $this, 'get_avatar' ) ); + return $avatar_defaults; + } + + /** + * Delete avatars based on a user_id + * + * @param int $user_id + */ + public function avatar_delete( $user_id ) { + $old_avatars = (array) get_user_meta( $user_id, 'simple_local_avatar', true ); + + if ( empty( $old_avatars ) ) + return; + + // if it was uploaded media, don't erase the full size or try to erase an the ID + if ( array_key_exists( 'media_id', $old_avatars ) ) + unset( $old_avatars['media_id'], $old_avatars['full'] ); + + if ( ! empty( $old_avatars ) ) { + $upload_path = wp_upload_dir(); + + foreach ($old_avatars as $old_avatar ) { + // derive the path for the file based on the upload directory + $old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar ); + if ( file_exists( $old_avatar_path ) ) + unlink( $old_avatar_path ); + } + } + + delete_user_meta( $user_id, 'simple_local_avatar' ); + delete_user_meta( $user_id, 'simple_local_avatar_rating' ); + } + + /** + * Creates a unique, meaningful file name for uploaded avatars. + * + * @param string $dir Path for file + * @param string $name Filename + * @param string $ext File extension (e.g. ".jpg") + * @return string Final filename + */ + public function unique_filename_callback( $dir, $name, $ext ) { + $user = get_user_by( 'id', (int) $this->user_id_being_edited ); + $name = $base_name = sanitize_file_name( $user->display_name . '_avatar_' . time() ); + + // ensure no conflicts with existing file names + $number = 1; + while ( file_exists( $dir . "/$name$ext" ) ) { + $name = $base_name . '_' . $number; + $number++; + } + + return $name . $ext; + } + + /** + * Adds errors based on avatar upload problems. + * + * @param WP_Error $errors Error messages for user profile screen. + */ + public function user_profile_update_errors( WP_Error $errors ) { + $errors->add( 'avatar_error', $this->avatar_upload_error ); + } +} $simple_local_avatars = new Simple_Local_Avatars; /** - * Upon installation, remove settings and local avatars from WordPress. + * more efficient to call simple local avatar directly in theme and avoid gravatar setup + * + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternate text to use in image tag. Defaults to blank + * @return string tag for the user's avatar */ -function simple_local_avatars_uninstall() { - $instance = new Simple_Local_Avatars; - $users = get_users( array( - 'meta_key' => 'simple_local_avatar', - 'fields' => 'ids', - ) ); +function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { + global $simple_local_avatars; + $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ); + + if ( empty ( $avatar ) ) { + remove_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); + $avatar = get_avatar( $id_or_email, $size, $default, $alt ); + add_action( 'get_avatar', array( $simple_local_avatars, 'get_avatar' ) ); + } + + return $avatar; +} + +if ( ! function_exists( 'get_avatar' ) && ( $simple_local_avatars_options = get_option('simple_local_avatars') ) && ! empty( $simple_local_avatars_options['only'] ) ) : + + /** + * Retrieve the avatar for a user who provided a user ID or email address. + * + * @param int|string|object $id_or_email A user ID, email address, or comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternative text to use in image tag. Defaults to blank + * @return string tag for the user's avatar + */ + function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '' ) { + global $simple_local_avatars; + + if ( ! get_option('show_avatars') ) + return false; + + $safe_alt = empty( $alt ) ? '' : esc_attr( $alt ); + + if ( !is_numeric($size) ) + $size = 96; + + if ( ! $avatar = $simple_local_avatars->get_avatar( '', $id_or_email, $size, $default, $alt ) ) : - foreach ( $users as $user_id ) { - $instance->avatar_delete( $user_id ); + if ( empty($default) ) { + $avatar_default = get_option('avatar_default'); + if ( empty($avatar_default) ) + $default = 'mystery'; + else + $default = $avatar_default; + } + + $host = is_ssl() ? 'https://secure.gravatar.com' : 'http://0.gravatar.com'; + + if ( 'mystery' == $default ) + $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com') + elseif ( 'blank' == $default ) + $default = includes_url( 'images/blank.gif' ); + elseif ( 'gravatar_default' == $default ) + $default = "$host/avatar/?s={$size}"; + else + $default = "$host/avatar/?d=$default&s={$size}"; + + $avatar = "{$safe_alt}"; + + endif; + + return apply_filters('get_avatar', $avatar, $id_or_email, $size, $default, $alt); } - // Remove settings from the database. - delete_option( 'simple_local_avatars' ); -} +endif; + +/** + * on uninstallation, remove the custom field from the users and delete the local avatars + */ + register_uninstall_hook( __FILE__, 'simple_local_avatars_uninstall' ); + +function simple_local_avatars_uninstall() { + $simple_local_avatars = new Simple_Local_Avatars; + $users = get_users(array( + 'meta_key' => 'simple_local_avatar', + 'fields' => 'ids', + )); + + foreach ( $users as $user_id ): + $simple_local_avatars->avatar_delete( $user_id ); + endforeach; + + delete_option('simple_local_avatars'); +} \ No newline at end of file From d33256fe442db97b5cc4c1a8074a5d558efc1e7d Mon Sep 17 00:00:00 2001 From: Eduard Florea Date: Fri, 17 Aug 2018 16:19:41 -0700 Subject: [PATCH 10/22] fix wrong issues URL --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 235a37c4..1f99c919 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "support": { - "issues": "https://github.com/10up/simple-local-avatars", + "issues": "https://github.com/10up/simple-local-avatars/issues", "source": "https://github.com/10up/simple-local-avatars" }, "require": { From a76d9aa8ac10606420e96b1fb50a0693ad53d5c2 Mon Sep 17 00:00:00 2001 From: Eduard Florea Date: Fri, 17 Aug 2018 16:22:58 -0700 Subject: [PATCH 11/22] remove autoload --- composer.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/composer.json b/composer.json index 1f99c919..98decb7b 100644 --- a/composer.json +++ b/composer.json @@ -21,10 +21,5 @@ }, "require": { "php": ">=5.3" - }, - "autoload": { - "files": [ - "simple-local-avatars.php" - ] } } \ No newline at end of file From 0242cc3c64812c404559ee4ea6d2139e791e0775 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Tue, 21 Aug 2018 13:02:09 -0400 Subject: [PATCH 12/22] Take advantage of .org language packs (WP 4.6+) Languages files have been imported into Rosetta already, by making these small changes we can automatically take advantage of those and any future translations. --- localization/simple-local-avatars-be_BY.mo | Bin 2705 -> 0 bytes localization/simple-local-avatars-be_BY.po | 60 --------------- localization/simple-local-avatars-de_DE.mo | Bin 2356 -> 0 bytes localization/simple-local-avatars-de_DE.po | 58 -------------- localization/simple-local-avatars-es_ES.mo | Bin 2149 -> 0 bytes localization/simple-local-avatars-es_ES.po | 59 --------------- localization/simple-local-avatars-fr_FR.mo | Bin 2272 -> 0 bytes localization/simple-local-avatars-fr_FR.po | 59 --------------- localization/simple-local-avatars-hu_HU.mo | Bin 2454 -> 0 bytes localization/simple-local-avatars-hu_HU.po | 83 --------------------- localization/simple-local-avatars-it_IT.mo | Bin 2153 -> 0 bytes localization/simple-local-avatars-it_IT.po | 59 --------------- localization/simple-local-avatars-nb_NO.mo | Bin 2311 -> 0 bytes localization/simple-local-avatars-nb_NO.po | 59 --------------- localization/simple-local-avatars-pt_BR.mo | Bin 2211 -> 0 bytes localization/simple-local-avatars-pt_BR.po | 61 --------------- localization/simple-local-avatars-ru_RU.mo | Bin 2808 -> 0 bytes localization/simple-local-avatars-ru_RU.po | 60 --------------- readme.txt | 3 +- simple-local-avatars.php | 3 +- 20 files changed, 3 insertions(+), 561 deletions(-) delete mode 100644 localization/simple-local-avatars-be_BY.mo delete mode 100644 localization/simple-local-avatars-be_BY.po delete mode 100644 localization/simple-local-avatars-de_DE.mo delete mode 100644 localization/simple-local-avatars-de_DE.po delete mode 100644 localization/simple-local-avatars-es_ES.mo delete mode 100644 localization/simple-local-avatars-es_ES.po delete mode 100644 localization/simple-local-avatars-fr_FR.mo delete mode 100644 localization/simple-local-avatars-fr_FR.po delete mode 100755 localization/simple-local-avatars-hu_HU.mo delete mode 100755 localization/simple-local-avatars-hu_HU.po delete mode 100644 localization/simple-local-avatars-it_IT.mo delete mode 100644 localization/simple-local-avatars-it_IT.po delete mode 100644 localization/simple-local-avatars-nb_NO.mo delete mode 100644 localization/simple-local-avatars-nb_NO.po delete mode 100644 localization/simple-local-avatars-pt_BR.mo delete mode 100644 localization/simple-local-avatars-pt_BR.po delete mode 100644 localization/simple-local-avatars-ru_RU.mo delete mode 100644 localization/simple-local-avatars-ru_RU.po diff --git a/localization/simple-local-avatars-be_BY.mo b/localization/simple-local-avatars-be_BY.mo deleted file mode 100644 index b71bf16760336c6e1564212fc77bfef846da4cc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2705 zcma)7O>9(E6uv6{jk@q>;X>nK2chqE1`+~8T$F-@1f+r1zuldAw=<8vd3Sv8PHT-O z(n`e?DTvlYA||qMTcm}Qw!^}e3zPeHE{rR;CMK>){LX#T&J2x)m)w5u-Jf&5^PTTb z|9D}?*8mm4G?zgd4}JHf*>Us zlbn=BCe&(1S_U*8swg0%sg7;^l?5fv$;DAH9KbvTO??jzqoBV7{WP2IPV!jw{Fd^)4Ry-Cx$m2B26%@zm0 zsvG`)o*he-)8Ij&WDt<-OXrJIaWqXbiu9C|Dy6B=)S)fv>m0AjrmTcfXhI0Xa_92* zmY345p_ZxZgxiE16+NkTi_@wZ$!boecQ;k0J3+#@212o#>XbM@Iw7>A!@uv)u5qyB z0~J}FU>=fcosR70h}F8PPVhQ+Kge64n+BcsMWnqqCJE+CsRkRV&pD$S`D9#Ed4qb14p3FcMplg@Qi(K53>sk^rUqWqi7!SHeO6VCcRcXk zQVDypylJUEhE(!P1&F8<+55qZ+Hi~`w|(a<0|ov##J4lC1pBL2@Pm? zr`2T01^2RGBKxRxuv|R2r??jkPRJC=I7q~Tl?gL(t%XK-qe?c)^tP(t?y8Bj@Qyd4 zaj%WHxuZ;nRV0&E8p^o4I;>ll>zp_hq*)C;s*+sH<@No}g9e>-| zb$d6PC4Byb^%;y$>=N;2viI=b&OXf+?OL`#_AW1G^VvDK?K8VH;O4NnNZEC=H?swM zE1S)*VsG*JZ3ig3g42!!2q5)_qtV9HjQuH__sL$hE0|qj7LE~b=6qne$RuuqmOF$k z+57+@=Uw7BTfY{bT|u1h9d}2Szz-y^fD{<{!d~vyD(sipJXgzAHI?}>~{#X z4nfcgS3lCU5qZri+lC5l$kAH{-d(@?JOBYm`EX;5sD2*v_}y7% zi|0gf#~&yi7nAI_2m}A1l!t8xOm_#(T(Gw}3o1S5Qn0Gah_dLKid(?HC%FNbDOv(p I3wIv_$N&HU diff --git a/localization/simple-local-avatars-be_BY.po b/localization/simple-local-avatars-be_BY.po deleted file mode 100644 index d52ef7bc..00000000 --- a/localization/simple-local-avatars-be_BY.po +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-11-03 19:09+0200\n" -"Last-Translator: \n" -"Language-Team: Web Geeks\n" -"X-Poedit-Language: Belarusian\n" -"X-Poedit-Country: BELARUS\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Лакальныя налады аватара" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Толькі карыстачы вызначанай катэгорыі могуць загружаць аватары (Аўтары і вышэй)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Аватар" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Загрузіць аватар" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Няма установленого лакальнага аватара. Выкарыстоўвайце загрузку, каб дадаць аватар." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Выдаліць лакальны аватар" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Замяніць лакальны аватар загрузіўшы новы малюнак ці сцерці лакальны аватар пазначыўшы опцыю выдалення. (па змаўчанні вернецца gravatar)" - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Лакальны аватар не ўсталяваны. Усталяваць ваш аватар на Gravatar.com" - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Вашых паўнамоцтваў не досыць для змены аватара. Каб змяніць лакальны аватар, звяжыцеся з адміністратарам сайта." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Лакальны аватар" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Дадаць запампоўку аватара да профіля карыстача, калі ў бягучага карыстача ёсць паўнамоцтвы. Генераваць такія ж памеры, як на Gravatar-е. Проста і лёгка." - diff --git a/localization/simple-local-avatars-de_DE.mo b/localization/simple-local-avatars-de_DE.mo deleted file mode 100644 index 95abc45afdbbdf8f69eb6cbb72b1270068e31fae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2356 zcma)7%Z?jG6m1~93@msoKw@#Tn-T6FJ0VeU05Ox9gg_=4B{RGhNae2U?i#nNOjY#^ zV*$znB=~^rBC?4*I=VLXfRCq}sFp(y$ucpUf`@E73oz~6x{0{;e{1>OUm1HSff6nzBz9QY0J z58w;H{v%QJ3~(Q~3;YWBCFcAC{0-0LqfyiXZXifle+&2$Py#OlzW{y={1x~$u>E)x z{RsRCcoHa{sN>uKhPXcfv3zxbLWIW%p`s@-j$wogA*%~ZRk~dU3wlub8pbB=R2IO<5w6vDBuV3cE(TJrIG-f+e&MBi^LKj%G z6&{l;e^RpZEXk<}o{c8SBcUbjmd;b5hD;Z19sf98Q=@UgU?lM-%l$rw-y~YC_(khn zuxBbvDvE}4bg6o%KcKA{iRiLf_>hz%$3CHJ4DMq(Fr_`rTlo7NlGKcn|D3zyxYFRL zP(n%)3*nOJiY^XF6ouKZq;j;cd=71qUo$-wW6@WI@(RKPxoi37({r@6TKe4BU=w2W z%^ojDS9x5Bw5BruHT4ggMU>7!Nb`P^Vw;R5Skmxcn6xwi%P^rY(qZ5sC~F*94lAZP zr^E0*xG!r9%-F-}Bx($sH^D_absmjrADWV+A#FV6Vvn10K?#VAN1>1wDregup3oWB z2F(*~Q);vqsjrCi3xgEpNNMFfYR%Xr+OlSsQy*WH@q27TE%pveYJnkjlWq$l8tdat zmnj*qm6?mTO^C*@_q0imOU9t_a0-y}H)cmF@VPWf8=P*HQ32 zI??HN<4!m3o}upP-pSLw?ul1AonEKY+Pt{AG2_)uI<0fa2MWa72V>0i{Hb4ou}Yr} z8dy~88#~+Q<1@4Gtk7=2Hr~*wk+7skXZp&6Mtqg`R7m&%EMD!MIvsaTfx#u=5G*WG z1i^arjtJY&6cTpO>$`XwWq5iEJ5&{!HRaePn*E!Ysk0J>#oH`KJ!*XrZy9WRA0NKx zVb5Ev(u&Sc?_{1>X*wU;$fO+6+a}EmAz6pNQS0yt`v9en?z2>v$ui|iPs%nqg9Jm9 zu(Zay^b_2KHP%?zJ}c-&duSq?q3K8{uJA{nEvLCxh>K!q+K*!ENh(I!58x)-LZOl| zQ%rAhn=;m-#GagQKO0I9M4D5Ht>yw{J*SzNk z6D@8Sq?nsIKs(H^i!u{|w{#(O#nW3su=^%x8Y$>m+0v+uG#_M5*ayKCiL+tm zd@yaMLa;b=HiM(2l3NNpy#pVYK?H?Afh?Flo6shuad402q z^e;h<0EYko diff --git a/localization/simple-local-avatars-de_DE.po b/localization/simple-local-avatars-de_DE.po deleted file mode 100644 index 479da08d..00000000 --- a/localization/simple-local-avatars-de_DE.po +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-01-18 14:17-0500\n" -"Last-Translator: Jake Goldman \n" -"Language-Team: \n" -"X-Poedit-Language: German\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Profilbild-Berechtigungen" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Erlaube ausschließlich Benutzern mit der Berechtigung zum Bearbeiten von Dateien das Hochladen von Profilbildern (Autoren und darüber)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Profilbild" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Profilbild hochladen" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Es ist kein Profilbild festgelegt. Klicke „Durchsuchen…“, um ein Profilbild hochzuladen." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Profilbild löschen" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Ersetze das Profilbild, indem du ein neues hochlädst, oder lösche das Profilbild (dann wird ggf. dein Gravatar angezeigt), indem du „Profilbild löschen“ auswählst." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Es ist kein Profilbild festgelegt. Lade dein Profilbild bei Gravatar.com hoch." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Du hast keine Berechtigung zur Bearbeitung von Mediadateien. Um dein Profilbild zu ändern, kontaktiere den Administrator dieser Website." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars (Einfache lokale Profilbilder)" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Fügt ein Feld zum Hochladen eines Profilbilds (Avatar) hinzu, sofern der Benutzer zum Bearbeiten von Mediadateien berechtigt ist. Generiert die erforderlichen Maße, genau wie Gravatar! Einfach und schlank." diff --git a/localization/simple-local-avatars-es_ES.mo b/localization/simple-local-avatars-es_ES.mo deleted file mode 100644 index 78833ca080232e59ecf8390270dce2df8550fee7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2149 zcmah~%WfP+6fH=24Isp0!Gguj&Q{VrGe#IQ;UVLg$igO;A5mae(|xC>?C!3n9v&uw zB@5Pw4+tB?5@m-fZqUr2fhXz zUJ~L(-~@OA{2Dk#%s;?iFh6;!*?$Fxyo7ld820}FxC6WcJOq9ZybXK+{1&+POtb%A zz)-^jpafoeRtRigKS)7fDsYr|4&yRLcyMI>U@OtV2=NF%f1VG2ZKkOuS&}@HP8#x6 zu4PIi#d%6jlecWBGJ2$PwxmYn#!QJfhD+Cc97{_Dr%F=Arcl-@UD}v#a>+(I1R4I^ zvvr)3Rd+GhC8b=*GNlu59p&nj>85GUze0zqsB%U|DZXT5H{tLbi_JPeaf5SqOu0^E z-sUWJ>q)bK_AinUpXjB9q%2u>FuV|{hnb$4dc@A-+i}O_XQMu};mN@X2-O`BNk8-2owi+0lJHk;6kgLz9WWk~(F-vNo*xMMgKl@CO}_A<)sK6fEz|=BqN8brNXK8eE`(L(^}vBax4w6L z^ii~NvChcSj@U%oWuj9^GN6s2a!4aO;4>8pekhBzb?Wy9Z@qoB*GC4s(&DhNNgfCr z(8s%*dwcY5TeM+kv{9o`xCHNGb(wjH6dkcF2GqF|?Q2|h7tKF_+)9G}aYt;N!AY)Oy%5O!VR%O?#55Tdh4Z88s5MK=q7jt&3?2F%Ro#9XKEv0EqI3` z5-(E?hdDqd=$=qAwuK9+Vsp6YK#OX)HrSj#TCia-tG?%zmC18xzEBzLE2Dqv7&Vqxt`xj;$ol zX{1fz^O~;(da*eix&nz!*0__i`#EL_SGA`%6x)z%d)0yn7y2||;H_?LU~n9b-lr)P zgjy<0R>h$oTBn?!a!96$swL(U)%y|*cs|o`8X9VYCd1o{g}AmJrfp##NfJa0pCOa3 z5;eOY{wZK_OaBUJvYv9EK?~619Zd4BG_!k4?5#e=evl~IuGJ7y!CpgKEOk=J3EMy= jT4_IUfwmng9Cx7=_zGrIi(D6S?lmdA6h277f@1L>8v(72 diff --git a/localization/simple-local-avatars-es_ES.po b/localization/simple-local-avatars-es_ES.po deleted file mode 100644 index d0b67eb2..00000000 --- a/localization/simple-local-avatars-es_ES.po +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-01-26 10:57+0100\n" -"Last-Translator: KLAMM \n" -"Language-Team: \n" -"X-Poedit-Language: Spanish\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Permisos de Local Avatar" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Sólo aceptar usuarios con permisos para subir avatares locales (Autores y superiores)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Avatar" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Subir avatar" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "No se ha configurado ningún avatar. Usa el formulario para subir tu propio avatar." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Eliminar avatar" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Substituye el avatar subiendo uno nuevo, o borrando el avatar actual seleccionando la opción de eliminar (en su lugar se utilizará Gravatar.com)." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "No se ha configurado ningún avatar. Configura tu avatar en Gravatar.com." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "No tienes los permisos necesarios. Para cambiar tu avatar contacta con el administrador del blog." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Añade un campo para subir un avatar a los perfiles de usuario siempre que éstos tengan los permisos adecuados. Redimensiona las imágenes de la misma manera que Gravatar. Simple y ligero." - diff --git a/localization/simple-local-avatars-fr_FR.mo b/localization/simple-local-avatars-fr_FR.mo deleted file mode 100644 index 24596e69deaf7f58dcee05acbb40173680261cd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2272 zcmZ`)O>Z1U5N#lQEpXsNf&+)j$+qGd?;6RN4MEt6i7ds$ve!|<0jYPUced@B?n!sg zI<`RK!T~sN;)uiz`FHpNH;x<-;=m8!4N_&o{39An?43 z^)A*ISg&LKfyEC!BgD_Z>%bR)zXIO`{sw#p_&4w-@L%9<;0MnN@fq+-;5WeEfo}na z&k6Aw@ECXq{2KTb&in)X3-6DgZ{qJE3CDc|d>iP1w}9UQKL`E-%zz6o3h^WGdmzV; zUTS!60>8ui0EqDQ0}2AK0;$BySl6)lLCX3;NYTOK9w6Ms^9uj9k*1!cAvuvjI;zUt z%9KW0(`OF7iJ4jPT&b~o*xEzi^9Mis`^u}sJ@v=g-? z_Eee6q@gmqn}#QC5N$FLGU~W3aha?mNYe73JG3|gOFl4^$r1CAl(mX1al~Y-k|X|} z)lVA4MeyRFsiPI`k*z4TWNe_ZoTzqOFak1D1rO5Pa>q4~SGo418 zRpz6C?bA4fvcIx&Y+YJ9<$Y{jwi0Bv;_K0jYC=&nufDT;e-PbvN^&!zI~e#rt#*68 zsN0Kr>(pE8zqi)!t={N%``vD5XM1Psl2lsFmGldu9|wYkYXaG2Ix z2ZK+d^~-%u8b4Al+A@hvAxWRshdO{pw5KMT3%|nTgfFrejp{tz$E3T*XrrZ~;6zS2@27kDz>E<|9hAFD-^P#SvM7 zGw(&22*8oD^D_sF;(*2Z8EnW?S`m*%OxroZc(4zqG{mJ#6>m4q3A`9vO;pZD14;!h z)A>)7%hsP1UDy!}BR@aO6eg^l>HVrKoh~@_w6c0I#EbzooNMFqVxvmXl(q@=)|jCF zNN1H(r!=v_!S)&#_9$#>iH#kh6te&``JW&Mb^j0o6}CNxFPxu&FwfBRiq&RUivyRx zLImXM#-f_aXxMdqE4eWM2&X#k890TInBfb_3OszQnw7L*^$FBbFej)R6Qk eQySAQE5eL0R`c@L({bT-O|vd-jypOXaq%DRA>W1o diff --git a/localization/simple-local-avatars-fr_FR.po b/localization/simple-local-avatars-fr_FR.po deleted file mode 100644 index fd0ba02d..00000000 --- a/localization/simple-local-avatars-fr_FR.po +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-01-27 00:16+0100\n" -"Last-Translator: Valentin Brandt \n" -"Language-Team: \n" -"X-Poedit-Language: German\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Permissions des avatars" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Autoriser uniquement les utilisateurs ayant les capacités d'envoyer un avatar sur le serveur (auteurs)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Avatar" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Envoyer un Avatar" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Il n'y aucun avatar local. Utilisez le champ de téléchargement pour ajouter un avatar local." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Supprimer l'avatar local" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Remplacer l'avatar local en envoyant un nouvel avatar, ou effacez-le (vous allez retomber à un gravatar, si disponible) en cochant l'option de suppression." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Aucun avatar local. Configurez votre avatar sur Gravatar.com." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Vous n'avez pas les autorisations nécessaire pour gérer les médias. Pour changer votre avatar local, contacter l'administrateur du blog." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Ajoute un champ d'envoi d'avatar pour les profils utilisateurs, si l'utilisateur dispose des autorisations pour gérer les médias du blog. Il est possible de générer de nouvelles tailles, à la demande ! Simple et léger." - diff --git a/localization/simple-local-avatars-hu_HU.mo b/localization/simple-local-avatars-hu_HU.mo deleted file mode 100755 index 4da228acdbccc6a0eca120397989af00c48a28f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2454 zcmZ`)zmMER6doY_x+Y1ZZ}$?SumQy75~4`C(_&e|d@GsyN@QufXxC8tI z_&M-r;LE`76GA)>+z0l7p8>x`%pbtt@P7ED5KF+jNaE*z1v~}35A^H(0E~buPYZDm zco+B(cLx3W4RT3nd7A7Dy%VS)9P_FQlw4EM4XH9AMew>!km+ z8AX<4Msg&bENGZ(BO}^VtRr%UhL#J;3$v#*TT*-E5~kj;C^&QVU?MFII8u^wE(Xe4 zWilJm70$Sj4nYNfIArTMBC95NHyK4dkXc0ip>?EH%5ZWFKt$L{^(9Wy~aosFTBxT963+Wc4_MFCMSWNdV-Ej?J&kVx< zjlFHT;^3b|$tWVZkS-KAGCd}#wb`$zvb3*U0&cOtCcGze*;QIO1!6qiHU0D3v$V1~ zbcrdvOvuqSBVH9ZIoGmRmoh(_y5nXMmBlD19FZFdu ziW@~%{ffPWd#NAy>PNK%CU;Oe6pdi>B3N;|-bW+a2WCi-q0Bf+ntp!q`AsAn=Kd#);^s|~go4OFJAgV#(Eik-srx#xnbQScrY-iw{7r4}lr zcGzA5iKcMDwvAO3TpY$W*fkwWoXb1w>-(mN@`9}mO%bm<8L!*Qnn6`iQ2W&`?cCT6 zwhES>jNlRs-=U3GyB)OJLHj(l&vnk6>$Epcw_2T6YiaxH_T^b!?Xb19h5dkmV0WA& z((y-b9m1;Yg6E)sTi?39`)+W4Hm{JG-Qyy-ob^luNjh}Cs~pM*Zt_U^4bQ4L6SOvh z)>+!v=(NwAZnaUtHEEH|FQPqR9l9eEsZ&W8IfI?v?0N_%^~ZNqHd2mtm<-=WWEKx0 zSg^}-&}rs3(Z_=w8pwDoi>3F2rUCdII|lv1f%4bGvlyvggNv|YE?v^0FkBLww8t8~ zWRjH!y8K2pO(!uE!aXSu(3LnIH=on;F!uqje2DuHo*wYz=$>1H!C>Bnr81e)2pw)v z9->R7JYkIpMST++JJimW2eAxklkBAYF16)hjI-zyAfQ0ANzpCvmY0u^UUTdl8*1#! zHG=gV(oMTpNSEWWop5pV01+0pPFRoA@?n;Zj~-O!#Nqc#d!IHx3417fMT|z4VqtWt zy5UxvWE_O3Jk(=O#dVeSEPBkpW^oi!`Ki|BeP^i)GGr_xzwbrHu#vf9(dNkLNNSTU zi*0P1vTFUgpRya-3 zfM<=hvKamp@xKa-H_VOXYGvUr=PHL6jHmM0Aq|nCnAyx5Y3jeF`- zP|+Ct_gOH}G7iH`XVeIiMySS_iSueSa^owdtTi6!lNsj8N$n`mujRm(2C3@?J#jcR J=s0+U;%`uAU5o$# diff --git a/localization/simple-local-avatars-hu_HU.po b/localization/simple-local-avatars-hu_HU.po deleted file mode 100755 index c015cb03..00000000 --- a/localization/simple-local-avatars-hu_HU.po +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2013-02-04 22:13+0100\n" -"Last-Translator: Zahalka Bence \n" -"Language-Team: Bence Zahalka\n" -"Language: magyar\n" -"X-Generator: Poedit 1.5.4\n" -"X-Poedit-Basepath: ..\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Lokális profilkép engedélyek" - -#: simple-local-avatars.php:120 -msgid "" -"Only allow users with file upload capabilities to upload local avatars " -"(Authors and above)" -msgstr "" -"Csak azok a felhasználók tölthessenek fel saját avatárt, akik fájlokat is " -"tölthetnek fel (Szerzők, vagy magasabb jogosultsági szintűek)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Profilkép" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Profilkép feltöltése" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "" -"Még nincs profilkép feltöltve. Saját profilkép hozzáadásához használd a " -"feltöltés mezőt!" - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Profilkép törlése" - -#: simple-local-avatars.php:152 -msgid "" -"Replace the local avatar by uploading a new avatar, or erase the local " -"avatar (falling back to a gravatar) by checking the delete option." -msgstr "" -"A meglévő profilkép lecserélhető egy új profilkép feltöltésével, vagy a " -"meglévő törlésével (ekkor a gravatar képed lesz használva), ha bepipálod a " -"törlés mezőt." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "" -"Nincs lokális profilképed. Állíts be magadnak egy profilképet a Gravatar.com " -"oldalon!" - -#: simple-local-avatars.php:161 -msgid "" -"You do not have media management permissions. To change your local avatar, " -"contact the blog administrator." -msgstr "" -"Nincs médiafájl-kezelési jogosultságod! A profilképed megváltoztatásához meg " -"kell keresned az oldal valamelyik adminisztrátorát." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Egyszerű helyi profilképek" - -#. Description of the plugin/theme -msgid "" -"Adds an avatar upload field to user profiles if the current user has media " -"permissions. Generates requested sizes on demand just like Gravatar! Simple " -"and lightweight." -msgstr "" -"A felhasználói profilhoz hozzáad egy profilkép feltöltése mezőt, ha a " -"felhasználónak van médiakezelési jogosultsága. A szükséges képméreteket " -"éppúgy legenerálja, mint a Gravatar. Egyszerű és pehelykönnyű." diff --git a/localization/simple-local-avatars-it_IT.mo b/localization/simple-local-avatars-it_IT.mo deleted file mode 100644 index dca4e99f991e274551970ca8ee9dce094a1e5387..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2153 zcmZ`)%WfP+6fGd(F~EYy0wIuYBqZBPx;^8F$aDz8OhRNS#+Dx_ut7E5*F9xdS2b1D z9&8>v7JLBTK$iRiD|Redpse@+B(@-Ns=NIdqm)#0x>R*oh4>u!E$|26@4(lAlV^l@ z88`zT0KW%*4V%A!KVz-0cK+YSCDHFYz&C++fSbUFz#ZTt-~{*&@H^la&vpJE10(Oh zfjRK%^FqLVJ3v8TDR7l|0rLuG9JsO_a3uzqQ3IHtjThtBT2XkChUAe9(os`uD+}6J ztP2X38qbbuXZMw6PimjSlqqkVV-vc~sq|EFp(NGpD&@Vh#;0_j4LccNFi+D!7uSpo7K-(&~`uzU%J4MmwsiHG@%sopKsx9Dh@>*76f~S#x00HkZ2REFQFr z?f`9_lMtWSxr3xUc@8P@%_yJ?2x+595B!e$l1C)&ZGL zMW3*XN$_H?i=$84XSSijlCgoN@`(F#K?%r`t5`^Lm9uMcpEMQB(S4*Jd;g zq0W|q=QT=)gE8WP0?F=i4a>k^g=HjGncGnVhibjExBGFjdVbDH zA`OWm#o3c$jQiJob>BZe+9`q*l@l#9CRZCg!a%l*_8N zF|TcIIRtiiwF`ZH7b>3VB#Z~VHSlqA0!k!Hjom1UigibY^0hUkH5Q*pH-ithV#y#m zDy3~zC{$4l9S?9pRh2B2L6@@CTw`H07KJAR9$c2}>}gLKOOvzK(YUA7rkKT6e@7cf zSIg8^kwSYg^vfecMOYtN+B!cEsk2XMFW_w>thwIOdg~1xcs9nO-5{3B_VI$wdBOWA z@?hc7OH#U*H_F&Ov?#RfVjW=yKL3Ybq6;R}K1N4#jaYjsF-?&xwjbL)*}R Z&4t)wC86nr&=yE_q208-kYXE3#edKqtTg}t diff --git a/localization/simple-local-avatars-it_IT.po b/localization/simple-local-avatars-it_IT.po deleted file mode 100644 index 283459a9..00000000 --- a/localization/simple-local-avatars-it_IT.po +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-01-18 21:35+0100\n" -"Last-Translator: MARCO \n" -"Language-Team: \n" -"X-Poedit-Language: Italian\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Permessi per Avatar Locali" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Consentire solo agli utenti con permessi di upload di caricare avatar locali (Autori e superiori) " - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Avatar" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Caricare l'Avatar" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Nessun avatar locale è stato definito. Usa il campo di upload per aggiungerne uno." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Cancella l'avatar locale" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Sostituire l'avatar locale caricandone uno nuovo, o cancellarlo (tornando al Gravatar) selezionando l'opzione di eliminazione." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Non è impostato alcun avatar locale. Utilizza Gravatar.com per impostarne uno." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Non hai i permessi necessari. Per cambiare il tuo avatar locale contatta l'amministratore del blog." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Aggiunge un campo per permettere l'upload di un avatar personalizzato agli utenti che dispongono di adeguati permessi. Ridimensiona l'immagine come Gravatar! Semplice e leggero" - diff --git a/localization/simple-local-avatars-nb_NO.mo b/localization/simple-local-avatars-nb_NO.mo deleted file mode 100644 index 10987c06580296bbf07217380535cf84c366afff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2311 zcma)7%Wfk@6fIzQ8CdXGuwZdVY!Z>~*cmYjJ%Gq0o>4?H6D1xr%&zRdZdbZp)l^m6 zn8yaef)7CA13-KM(k$3TEZDJRfmrbY`~VWCx}Awl5@}kh9QUJcoqNx@H-Eiyrbq3(Gx=a1iT7-2KXEBRp9Ty*MWZnZvg)VZUf(WQiun@FM;0z{{X%Q z>^~*MOTa1c82AnFbL{yC_zUifr-gU{xQatU+_!;m0`CA1ffkqpe+61#=UE|s2L1pH z@gF?bpaFh``>%lrUtgdga4T?>cpmEtR=99veIcZ1VTBqX+@mY-5nE~MNNSQ3>7}Kr zER0NPsJKYU8>$>zDy)m7DaI4UX#aMw2w_isUdAVjpT&qc7X+C#^Ye5CFk@E&XYRhMxaHa zYcw$0%Ym^PTXmsh{pP8-(@O| zZdRF#dM2Tf_hquaJ~cKiEjt$*o2`49t-IQqQB5dn{OVc2O#GQiOsfbn^Xd zqTs783U29L4)DPkZbK7j^FB7{tb$HakL5U_*8S+fpxb?P`XWKATWHx5dz^(BUKNA} z8*+g^@SG`;k@K}5C+Lt|!vD=kf%Q}Dz`}9Vw^hymH+>$N3CTRKU=9i=oQ;{T&I3OfD6_0EUtkROppKqhm|-kFtn{f6p-(T;;Ve)XWp<5n{QoF| z_@uN(=rEtpsT|YFEn|n$Ls8JkXms*$hM%jVYn{hq)Mj3~C42Z<%M1B0NV7&#yW@N{*T_rC!z|2wEz{B%L<\n" -"Language-Team: \n" -"X-Poedit-Language: German\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Innstilling for lokale profilbilder" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Kun brukere med rettigheter til å laste opp filer, kan legge inn nye lokale profilbilder. (Forfattere og høyere)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Profilbilde" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Last opp profilbilde" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Et lokalt profilbilde er ikke definert. Bruk skjemafeltet over for å laste opp et nytt lokalt profilbilde." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Slett lokalt profilbilde" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Erstatt det lokale profilbildet ved å laste opp et nytt profilbilde, eller slett det lokale profilbildet (vil gå tilbake til å vise gravatar) ved å krysse av valget om sletting." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Et lokalt profilbilde er ikke definert. Definer ditt profilbilde på Gravatar.com." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Du har ikke rettigheter til å redigere media. For å endre ditt lokale profilbilde, ta kontakt med administratoren for nettsiden." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Legger til et felt for opplasting av lokale profilbilder dersom brukeren har rettigheter til å redigere media. Genererer riktig størrelse ved behov akkurat som Gravatar! Enkelt og greit." - diff --git a/localization/simple-local-avatars-pt_BR.mo b/localization/simple-local-avatars-pt_BR.mo deleted file mode 100644 index ccf288a7415caf49c5d90034a76e95376087c033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2211 zcma)7%ZemL6b*HJl@IW-5Oi^8*Nv0eRoyVOIV$$cp{0AK=&l~d0T)r3QCZQQnUTh$ z${KX3;KHRJ(25KQuEZ~>m9AVWh%1*a`~krenOQGkU=pHFMrSYli1} zj5jbo#drzh4-Eg%V~jljUIjh{{2BNP@K@k#z`uYufd2ybfNwp{*gfE9z%PNn0bd37 zpJ40-;23xg{2cf@_WT3<4)b50tj{lT$%}p+@O9u9z(e3Sz>k1`1MdJoc$%@VfR{jj z{>C%)`TM{w<|jZLUp)wcVajk7dlusghJSEn_25X>!tfm6xcT#(f7?kCL%bk9;+AW2 zWu|yS11YkEtRiQGrc$ec%!DC1AUhNkJFP`w>yJZjC>M$3R0^F-W27ofNH;|xG`HBK z#m7zRMC80k=-e4gnY<8mQ`h%jrBj)gnLtDdzNAAt7XEL@cB=T;zQ}|X zl&P3!P0Z}5n$!!Zy9k2aQY#Bd8ZyF$bSe;gNfYJtEN^b-F@&+o!-wuYGos?)|3vX5 zA--~5$Zi+egm{*zaYdD(v9v>Qi~O4HF)w*vX3|O!6C{ML>lZHz{5tr3ocz;$PXcHb9hqL!ZYNJ`PT4Q;~IlVmuV_ zh5zoWpVTE#rA4Jf))Z{H2!@^2c{D})P&rBz70S|(k3=IENPwpz_d;4xPEX-JUZkQf z&~l*HC{~5#v8@8>X9_7Mxh$ly(3;XA>uPl_VjCPL!5yK!7NeP@RwATM*lB@8rEPF* zQkew1E;T_S8=eCV zwZ3!Kdq3D-tkb+O1EGV1B321X647>FT7(gth>`ROFGtbY3^ozPR@B)J+FOX=h#Oqy z56L`X5$(zhBHhjSgx-b{vq{*;`+I55W#&8KU2G{*he`!K!ShGia5v~G7=jIEJ0t3X zXP3eTL~H(aPr1VC2~IrOxp#Q9_;8B8jKyA^e?-m>Kmd$N#>ft>lh2yAfKqr~DoAqH zIe3GZ2IzGEKjWsCS}Jrsc`IvX+&Y+t75Pke)1T0NSf5XSfRB0a(&#J>fesZcLuI(x z@`OWuxtHcG@M?dRg2*wHwb+oQ>S^N zLV`-Fi9jZ9mObL1*=A!|k8qN=FGT~TbC=cJAa7BOKvKyyM>|z4`(J__nT}uumGPp_ zr#})L2SnhTaU8rFPe?;zm0NX$KW&~mi1qz~dUzL8=qFHR9BL%}WSyP5zOm9esS#Iw zR}~Mu4kfE&fOR43l0!g?MRgSo%*e~4TFyz8(+8dfBvsiI;#dPup0&)Sm?3> diff --git a/localization/simple-local-avatars-pt_BR.po b/localization/simple-local-avatars-pt_BR.po deleted file mode 100644 index 3043f100..00000000 --- a/localization/simple-local-avatars-pt_BR.po +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-12-28 13:18-0300\n" -"Last-Translator: Billy Blay \n" -"Language-Team: Billy Blay \n" -"X-Poedit-Language: Portuguese\n" -"X-Poedit-Country: BRAZIL\n" -"X-Poedit-SourceCharset: utf-8\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Permissões do Local Avatar" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Só aceitar usuarios com permisões para enviar avatares locais (Autores e superiores)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Avatar" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Enviar avatar" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Não há nenhum avatar configurado. Use o formulário de envio para adicionar um novo avatar." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Deletar avatar" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Substituir o avatar enviando um novo, ou apague o avatar atual selecionando a opção de deletar (em seu lugar se utilizará o Gravatar.com)." - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Não há nenhum avatar configurado. Configure seu avatar em Gravatar.com." - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Você não tem permissão para mudar seu avatar contate o administrador do blog." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Simple Local Avatars" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Adicione um avatar no campo de upload de perfis de usuário se o usuário atual tem permissões de mídia. Gere tamanhos solicitada como no Gravatar! Simples e leve." - diff --git a/localization/simple-local-avatars-ru_RU.mo b/localization/simple-local-avatars-ru_RU.mo deleted file mode 100644 index 122c72d9e59fe476a8efe730db6f765791fb8c69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2808 zcma)7-%lJ>6u#Q}3-!St4?bu-eWNKe?9!&ets0TiO41($s8QeU?p$^UX6LRmvmi#3 z0#@446yuMmF~-C`G`^UHmUasTAB}H!5)*we#u)zq{{a)fb7z6w)~b^XXJ_uY=X~e; zzPbGR_})(hu19b`jr$$kkKz6WH(zv*5LXcQA>NPp1L6~i2JtDxKM;=~{)IS*_}slh zyn*;G;swN?5uZdX?h)cq#2Lg%#B+#E?D-S%8N_ey%P@S8CN9>0L_CDJ=K&$=i2aD4 zBYxY8uRMsJc>W#nS;XHS%A)8J;wL;4BFfqe5CqZ$S_!0yy}0>8OMCHLNVgoI{Lb|- z{~GYTm}E$DS|&20dM(h>qX}OH9wnOUv5Ke`=?OnjG5HgeR1}r!QKZ5oTdc^Ks><^v z)l^jV?9y=+sz@f-6sb4sDo&I~vHv!nbx5A7%Fv_9dYn+;PboScW&QWjm|v|0 z3Wz+clq<=M;=isKu=vDL6{ti}pi44nVHPLsLzX}zyCB3V-H}LsOtDH_8dJbtqgh># zw&#|~4hFZRtL|O*o{5#^;C7;<=aKAa=Ze!|FiSEB^o*q{rWrq}fLqMh+Fp`1S@Z)x z@j(pJozdSuUQFEs^`xRBmI*zIdRpxlqpB9jQU;|xn~JloB7Rr~pis@UM(iOS5hQ8h z@7UBm0hGL(p0$++x$&dc?3?2PLIRg$Du=p7VKjjY>4jwM#`wrxCgbBO0SsqUP5V4>2Z}>Z?jWK0q1=I79}t|7F`99afC($$gV0W_s*^JGLwX)>!~VXP zic@Y>e-X)Hxekq-aV4w&p8A?IqHzc$&i0-Hjn;7%$gpc?X;9b0B$~y_nX$3qfm3vB z=;+Ys!1(a#Q(eM*Y_`mbX_!^hOy|>!WNzSL-89lgvz{)HU1_BAcyZP=$gGq34!^e2 z_e|4lq?hoB0vqW??At;SPF=(Eau1ocbk1y;CZUXdi+bq=tX?%+cim=pWk76Uvx%~| z&~Fj=mR&L*p};0epT#q9WG#W4Ap&>PtdY5nKMWU`ZgFb51T>h5(Qjgk?PJd|YpD2@ zoo5aO0INxW%n;YjmMhE$t&uRjFqh3W)WAd;z72HeqCEU&x@2y4kR{9)x2*#hnx|-F zf!}1b9a~J}&P|;~xdKL8;3DYE+^kx>o0#Kr$J-W2R^)s~mre@!)D`ASur&XVbD!ufV!*Ex^f-_{-Iy4e7Xl|5w5 zv6?QW=gr!FVLnAJ+yxQ-mmk`@-2jqR)`8{QVv3sf^I5T`g?qVZ_S$|wtTsCyA~D7e zE$%QLv$2Bv28!@kY+Erw?*r&1h}?2Imo??^8=7E^&FoobKKw>x;4?i$#_^Li-^ykTfC`Zt=@3O-yWPo Ag8%>k diff --git a/localization/simple-local-avatars-ru_RU.po b/localization/simple-local-avatars-ru_RU.po deleted file mode 100644 index 28146a06..00000000 --- a/localization/simple-local-avatars-ru_RU.po +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2010 Simple Local Avatars -# This file is distributed under the same license as the Simple Local Avatars package. -msgid "" -msgstr "" -"Project-Id-Version: Simple Local Avatars 1.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-local-avatars\n" -"POT-Creation-Date: 2011-01-18 16:36:12+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2011-04-03 00:40+0200\n" -"Last-Translator: seo-semjanin \n" -"Language-Team: seo-semjanin \n" -"X-Poedit-Language: Russian\n" -"X-Poedit-Country: RUSSIAN FEDERATION\n" - -#: simple-local-avatars.php:104 -msgid "Local Avatar Permissions" -msgstr "Локальные настройки аватара" - -#: simple-local-avatars.php:120 -msgid "Only allow users with file upload capabilities to upload local avatars (Authors and above)" -msgstr "Только пользователи определенной категории могут загружать аватары (Авторы и выше)" - -#: simple-local-avatars.php:128 -msgid "Avatar" -msgstr "Аватар" - -#: simple-local-avatars.php:132 -msgid "Upload Avatar" -msgstr "Загрузить аватар" - -#: simple-local-avatars.php:148 -msgid "No local avatar is set. Use the upload field to add a local avatar." -msgstr "Нет установленого локального аватара. Используйте загрузку, чтобы добавить аватар." - -#: simple-local-avatars.php:151 -msgid "Delete local avatar" -msgstr "Удалить локальный аватар" - -#: simple-local-avatars.php:152 -msgid "Replace the local avatar by uploading a new avatar, or erase the local avatar (falling back to a gravatar) by checking the delete option." -msgstr "Заменить локальный аватар загрузив новое изображение или стереть локальный аватар обозначив опцию удаления. (по умолчанию вернется gravatar)" - -#: simple-local-avatars.php:158 -msgid "No local avatar is set. Set up your avatar at Gravatar.com." -msgstr "Локальный аватар не установлен. Установить ваш аватар на Gravatar.com" - -#: simple-local-avatars.php:161 -msgid "You do not have media management permissions. To change your local avatar, contact the blog administrator." -msgstr "Ваших полномочий не достаточно для смены аватара. Чтобы сменить локальный аватар, свяжитесь с администратором сайта." - -#. Plugin Name of the plugin/theme -msgid "Simple Local Avatars" -msgstr "Локальный аватар" - -#. Description of the plugin/theme -msgid "Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight." -msgstr "Добавить закачку аватара к профилю пользователя, если у текущего пользователя есть полномочия. Генерировать такие же размеры, как на Gravatar-е. Просто и легко." - diff --git a/readme.txt b/readme.txt index 6ead59e3..bbfa8a95 100644 --- a/readme.txt +++ b/readme.txt @@ -2,9 +2,10 @@ Contributors: jakemgold, 10up, thinkoomph Donate link: http://10up.com/plugins/simple-local-avatars-wordpress/ Tags: avatar, gravatar, user photos, users, profile -Requires at least: 3.5 +Requires at least: 4.6 Tested up to: 3.6 Stable tag: 2.0 +Text Domain: simple-local-avatars Adds an avatar upload field to user profiles. Generates requested sizes on demand just like Gravatar! diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 44de848e..c7a7cf55 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -7,6 +7,7 @@ Author: Jake Goldman, 10up Author URI: http://10up.com License: GPLv2 or later + Text Domain: simple-local-avatars */ /** @@ -21,8 +22,6 @@ class Simple_Local_Avatars { * Set up the hooks and default values */ public function __construct() { - load_plugin_textdomain( 'simple-local-avatars', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' ); - $this->options = (array) get_option( 'simple_local_avatars' ); $this->avatar_ratings = array( 'G' => __('G — Suitable for all audiences'), From 6f6b0098cbde9eb046148908e5208d68df138594 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Tue, 21 Aug 2018 13:13:42 -0400 Subject: [PATCH 13/22] Add a missing text domain. See #2. Co-authored-by: Kniebremser --- simple-local-avatars.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index c7a7cf55..78d410cf 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -278,7 +278,7 @@ public function edit_user_profile( $profileuser ) { echo "\n\t
"; endforeach; ?> -

+

From 1d5b74b54752027a449b9aefa48d2de5d7f5567f Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Tue, 21 Aug 2018 13:22:36 -0400 Subject: [PATCH 14/22] Localize settings descriptions in the appropriate place. You can't localize a variable because there's no way for the parser to know what string(s) will be translated in that spot. --- simple-local-avatars.php | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 78d410cf..4fc87709 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -153,8 +153,28 @@ public function admin_init() { } register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); - add_settings_field( 'simple-local-avatars-only', __('Local Avatars Only','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'only', 'desc' => 'Only allow local avatars (still uses Gravatar for default avatars)' ) ); - add_settings_field( 'simple-local-avatars-caps', __('Local Upload Permissions','simple-local-avatars'), array( $this, 'avatar_settings_field' ), 'discussion', 'avatars', array( 'key' => 'caps', 'desc' => 'Only allow users with file upload capabilities to upload local avatars (Authors and above)' ) ); + add_settings_field( + 'simple-local-avatars-only', + __('Local Avatars Only','simple-local-avatars'), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'key' => 'only', + 'desc' => __( 'Only allow local avatars (still uses Gravatar for default avatars)', 'simple-local-avatars' ) + ) + ); + add_settings_field( + 'simple-local-avatars-caps', + __('Local Upload Permissions','simple-local-avatars'), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'key' => 'caps', + 'desc' => __( 'Only allow users with file upload capabilities to upload local avatars (Authors and above)', 'simple-local-avatars' ) + ) + ); } /** @@ -213,7 +233,7 @@ public function avatar_settings_field( $args ) { echo ' '; } From 89df35ff59208df597812039ee0cbaa40915e484 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Mon, 10 Sep 2018 22:06:56 -0700 Subject: [PATCH 15/22] Add support for getting and updating via the REST API --- simple-local-avatars.php | 46 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 19d58d6d..8a769c54 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -48,6 +48,8 @@ public function __construct() { add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); add_filter( 'avatar_defaults', array( $this, 'avatar_defaults' ) ); + + add_action( 'rest_api_init', array( $this, 'register_rest_fields' ) ); } /** @@ -472,6 +474,48 @@ public function unique_filename_callback( $dir, $name, $ext ) { public function user_profile_update_errors( WP_Error $errors ) { $errors->add( 'avatar_error', $this->avatar_upload_error ); } + + /** + * Registers the simple_local_avatar field in the REST API. + */ + public function register_rest_fields() { + register_rest_field( 'user', 'simple_local_avatar', array( + 'get_callback' => array( $this, 'get_avatar_rest' ), + 'update_callback' => array( $this, 'set_avatar_rest' ), + 'schema' => array( + 'description' => 'The users simple local avatar', + 'type' => 'object', + ) + )); + } + + /** + * Returns the simple_local_avatar meta key for the given user. + * + * @param object $user User object + */ + public function get_avatar_rest( $user ) { + $local_avatar = get_user_meta( $user['id'], 'simple_local_avatar', true ); + if ( empty( $local_avatar ) ) { + return; + } + return $local_avatar; + } + + /** + * Updates the simple local avatar from a REST request. + * + * Since we are just adding a field to the existing user endpoint + * we don't need to worry about ensuring the calling user has proper permissions. + * Only the user or an administrator would be able to change the avatar. + * + * @param array $input Input submitted via REST request. + * @param object $user The user making the request. + */ + public function set_avatar_rest( $input, $user ) { + $this->assign_new_user_avatar($input['media_id'], $user->ID); + } + } $simple_local_avatars = new Simple_Local_Avatars; @@ -568,4 +612,4 @@ function simple_local_avatars_uninstall() { endforeach; delete_option('simple_local_avatars'); -} \ No newline at end of file +} From b1a7b2308550638fe24ab66be28236aa3d5aa448 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Thu, 13 Sep 2018 14:50:11 -0600 Subject: [PATCH 16/22] Revert "Merge pull request #8 from eflorea/master" This removed the ability for subscribers to upload. Trying another method. This reverts commit 172f563fea0e1e5287fb7b8ec19ca3d7c7849339, reversing changes made to 4d70c3bd9ceda6a7e09532202d1a9d373d8b3743. --- simple-local-avatars.php | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 19d58d6d..b004a7fa 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -271,6 +271,11 @@ public function edit_user_profile( $profileuser ) { '_wpnonce' => $this->remove_nonce, ) ); ?> +

+
+ + +

  simple_local_avatar ) ) echo ' style="display:none;"'; ?>> @@ -345,6 +350,54 @@ public function edit_user_profile_update( $user_id ) { if( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) return; + // check for uploaded files + if ( ! empty( $_FILES['simple-local-avatar']['name'] ) ) : + + // need to be more secure since low privelege users can upload + if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { + $this->avatar_upload_error = __('For security reasons, the extension ".php" cannot be in your file name.','simple-local-avatars'); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; + } + + // front end (theme my profile etc) support + if ( ! function_exists( 'wp_handle_upload' ) ) + require_once( ABSPATH . 'wp-admin/includes/file.php' ); + + // allow developers to override file size upload limit for avatars + add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function + $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( + 'mimes' => array( + 'jpg|jpeg|jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + ), + 'test_form' => false, + 'unique_filename_callback' => array( $this, 'unique_filename_callback' ) + ) ); + + remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); + + if ( empty($avatar['file']) ) { // handle failures + switch ( $avatar['error'] ) { + case 'File type does not meet security guidelines. Try another.' : + $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); + break; + default : + $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); + } + + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + + return; + } + + $this->assign_new_user_avatar( $avatar['url'], $user_id ); + + endif; + // handle rating if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) From 6d72be68629bf32160ea008fad5016d04720da51 Mon Sep 17 00:00:00 2001 From: Eduard Florea Date: Mon, 22 Oct 2018 19:40:52 -0700 Subject: [PATCH 17/22] add compatibility with plugins to upload images to Cloud storage (Azure Storage, AWS S3) (#14) * use media_handle_upload instead of wp_handle_upload, update plugin version. See #16 --- composer.json | 2 +- readme.txt | 3 +++ simple-local-avatars.php | 29 +++++++++++++---------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 98decb7b..0fc58102 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "10up/simple-local-avatars", "description": "Adds an avatar upload field to user profiles. Generates requested sizes on demand just like Gravatar!", - "version": "2.0", + "version": "2.1", "type": "wordpress-plugin", "keywords": [ "wordpress", diff --git a/readme.txt b/readme.txt index bbfa8a95..9367fc86 100644 --- a/readme.txt +++ b/readme.txt @@ -43,6 +43,9 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei == Changelog == += 2.1 = +* Add compability to use plugins to upload avatar image to cloud (Azure, AWS S3 etc) by using media_handle_upload instead of wp_handle_upload + = 2.0 = * Choose or upload an avatar from the media library (for user's with appropriate capabilities)! * Local avatars are rated for appropriateness, just like Gravatar diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 5d63904f..7fb7b718 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -3,7 +3,7 @@ Plugin Name: Simple Local Avatars Plugin URI: http://10up.com/plugins/simple-local-avatars-wordpress/ Description: Adds an avatar upload field to user profiles. Generates requested sizes on demand, just like Gravatar! Simple and lightweight. - Version: 2.0 + Version: 2.1 Author: Jake Goldman, 10up Author URI: http://10up.com License: GPLv2 or later @@ -273,11 +273,16 @@ public function edit_user_profile( $profileuser ) { '_wpnonce' => $this->remove_nonce, ) ); ?> +


+

  simple_local_avatar ) ) echo ' style="display:none;"'; ?>> @@ -363,14 +368,14 @@ public function edit_user_profile_update( $user_id ) { } // front end (theme my profile etc) support - if ( ! function_exists( 'wp_handle_upload' ) ) - require_once( ABSPATH . 'wp-admin/includes/file.php' ); + if ( ! function_exists( 'media_handle_upload' ) ) + require_once( ABSPATH . 'wp-admin/includes/media.php' ); // allow developers to override file size upload limit for avatars add_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function - $avatar = wp_handle_upload( $_FILES['simple-local-avatar'], array( + $avatar_id = media_handle_upload( 'simple-local-avatar', 0, array(), array( 'mimes' => array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', @@ -382,26 +387,18 @@ public function edit_user_profile_update( $user_id ) { remove_filter( 'upload_size_limit', array( $this, 'upload_size_limit' ) ); - if ( empty($avatar['file']) ) { // handle failures - switch ( $avatar['error'] ) { - case 'File type does not meet security guidelines. Try another.' : - $this->avatar_upload_error = __('Please upload a valid image file for the avatar.','simple-local-avatars'); - break; - default : - $this->avatar_upload_error = '' . __('There was an error uploading the avatar:','simple-local-avatars') . ' ' . esc_html( $avatar['error'] ); - } - + if ( is_wp_error( $avatar_id ) ) { // handle failures. + $this->avatar_upload_error = '' . __( 'There was an error uploading the avatar:', 'simple-local-avatars' ) . ' ' . esc_html( $avatar_id->get_error_message() ); add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); - return; } - $this->assign_new_user_avatar( $avatar['url'], $user_id ); + $this->assign_new_user_avatar( $avatar_id, $user_id ); endif; // handle rating - if ( isset( $avatar['url'] ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { + if ( isset( $avatar_id ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); From 17cfe24b41782e986e1172f3226c3a54f9875bc3 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Mon, 22 Oct 2018 20:49:15 -0600 Subject: [PATCH 18/22] Fix a long-standing plugin header formatting issue --- simple-local-avatars.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 7fb7b718..47685e2a 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -1,14 +1,14 @@ Date: Mon, 22 Oct 2018 21:04:36 -0600 Subject: [PATCH 19/22] Readme updates for 2.1 --- readme.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 9367fc86..f3d95831 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: http://10up.com/plugins/simple-local-avatars-wordpress/ Tags: avatar, gravatar, user photos, users, profile Requires at least: 4.6 Tested up to: 3.6 -Stable tag: 2.0 +Stable tag: 2.1 Text Domain: simple-local-avatars Adds an avatar upload field to user profiles. Generates requested sizes on demand just like Gravatar! @@ -44,10 +44,14 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei == Changelog == = 2.1 = -* Add compability to use plugins to upload avatar image to cloud (Azure, AWS S3 etc) by using media_handle_upload instead of wp_handle_upload +* *New:* All avatar uploads now go into the media library. Don't worry - users without the ability to upload files cannot otherwise see the contents of your media library. This allows local avatars to respect other functionality your site may have around uploaded images, such as external hosting. +* *New:* REST API support for getting and updating. +* *New:* Use .org language packs rather than bundling translations. +* *Fixed:* Avoid an `ArgumentCountError`. +* *Fixed:* A couple of internationalization issues. = 2.0 = -* Choose or upload an avatar from the media library (for user's with appropriate capabilities)! +* Choose or upload an avatar from the media library (for users with appropriate capabilities)! * Local avatars are rated for appropriateness, just like Gravatar * A new setting under Discussion enables administrators to turn off Gravatar (only use local avatars) * Delete the local avatar with a single button click (like everywhere else in WordPress) @@ -105,6 +109,9 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei == Upgrade Notice == += 2.1 = +*Important note:* All newly uploaded local avatars will appear in the media library, even when uploaded by contributors or subscribers. However, this does not give them access to the media library. + = 2.0 = Upgraded to take advantage of *WordPress 3.5 and newer*. Does not support older versions! This has also *not* been tested with front end profile plug-ins - feedback welcome. Note that several language strings have been added or modified - revised translations would be welcome! From 174958f56ebbfb07c876c5bbffdffa3a443ebbf3 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Mon, 22 Oct 2018 21:08:04 -0600 Subject: [PATCH 20/22] Update screenshot --- screenshot-1.png | Bin 27970 -> 76478 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshot-1.png b/screenshot-1.png index a5ab97f921940a44679ac683353db475da3e511c..ebd81d0be2e84c9a9b0764df91555ab4560dca71 100644 GIT binary patch literal 76478 zcmc$^Wl-GTvM!7zKp?m~3=Tm<7@XivkU$_<(BLw-yEC}EyF+kycXxMpzmWev=j{E~ z`|VcU^I_Iht@%x_?$z=<-7^8-WJEuH!219J0r62>Oh_IA;$0O41hfPk)a%ZYzvcu4 zB(0CQ&{su!$ipQM1D!dd*0Y-ydPI7D6l(VjDGZ+sY7B}f77S_~i0_<=Qw4GqsNIP3 z!kLpW$z<@0{Ll=*);omdf$OFzP{i`!Y`my6FL94H2n6DCF9o^YXrjIzqva6*cztsR zzMV+|eqA8^-!>rD;a-=2-=_ z^XLK$G^ zzW?GjA#C}nDUN(j-?ThytiI$IhmaY1G~6SL{qt%we18b}Xr$QIpd#f?0`bYrz|E;L z#yR^>#UH2HIy!+QIVlES=SL7ys0`o7mj~zAoyZ>J$$iPl>c$E9H#gk+Y>4eP4f~dX zA9fNA|J2g!Xg6w({E4Xw1RkszF*fPnmEB-S+v4?!RvH&yUG3f6_f%r<6uQcHQ#}<{ zZq?1SxK7aMY#-Zys?)l-AK2N{?08gumHWdT7~vP(ZR20Qn`NW*5&Or1`sy22lix9qJhv@I$V z2?z6o0mSb~p%7kk8%6Z^x%YjLGrfRRlxF1^X>|?zT<%h4eoolXv)J(7ra;TW+|sgI z2_GxfRnLYPwO{c@)76xS>G4qEM(@13|C_pE~A0>+u=*>&ZO zBY(^v4}n&(Cp@Tc)q$TNo@$eox7mQunMP;*d}#dg!Lh@IGf4NwNbSsZC6!S0ysu)t zx8^nF-m>uvKFzth@eWAJ`*3k++y=KJHgfaDBqyDe&x}EaLG-wM_lzGsRz(9;A2q>@G?MTsvG@rGCz7k|;5 zDI8vn%EiQIk8m81Ll>1%c1w+9YQHRrM9IbI|&ZPo~n_R@1iE0yN#$h zFLG;?p4K1C@KoB596-l|;d|EOCdfP0p;M85m&Y3#6N7JQiz1rh{cuH(b%

QI?9 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%0AGS|k`7wTV7OB+* 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 literal 27970 zcmZ^~1yEc;yDf?Yw-DSlKyVq{A!xAR1Pku&?(Q1g354M8?l8E!&fqq+C- zdsDk=s-}AH-rfE6H*0-sb%c_F6dE!iG87aPnvC>UWhf{ZAQTkz6e8^VFE(r?R_|W~ z&Jvo=Dt4yMZU&AfP@=|mh9=}PHU?%U$|eTJ9u6ZW0#Hz}P)c&D5^wj*NBfH}FOX6X zmBD07n#iWOy4l0E@#&$)r9ZAS)v-$tZziS*tgNi9t*x zzT%)FE}cHE%@5UDaE-T?tEY}zvoR&bC5HW=E74?gH!-Q*xI0>GyMchJn}K_;Z)Ig= zRheNXCLT)l_np9dVjrAOLnX3rnbWu!~6 zHZLFV)O(yR{5`vQj%wcWY}^jlmAITpAKbmXdA&J&SXE$9j4SPB(#^Nm5D$~28g1>T zCnNlmR!X~Srgl2=T@po!_JK`q7SdVM7pJe+N|J6{*KZ@?oad0c zvIwW{#*#_M8I)^d;opv$+Umi)KoOmgi<_w~d!CN+!kx`&mDoNX57XV(o3*)lQxvG# ziP?<&jA}cmxvhoi+3l#sJHO$xuCfM2hXBd+8K@7k4vH4_TkA7hJ6EqeD~p>u*H_zT z`+>@a%4DPk-5Vl?Ka8D1paATT^YJwaR+~Kq=jZ2lcXvTxlgdmHRO&*g6sVF{9-IFPXlUW^Z4oRDaXes z+|3f|Yfwk9$lKFfPHp|uWZA`3&GGrM1r%NJEbJF3D2pYTucE5%D<>T&B3K$LZ)B7V zO{f$|Sj_vM05DempZy(GlA($}7f6VVp=dJCYueIlTH~;+l@|by8iT@LH!XGTzAdgd zo~zr`oHg3rb#>Wn+O+9ZOm*o!JFiL zl?~2H2SdJ0I;pp^eW?r zOk1F6r2;j*l3H7bD`O?~ait(-k^Ghzn29sOC+z^LbCMDbyW5bUvlnX5HSXtPE+nQquk)fO-p` zq=y67IWjFWt@_N_2I))kQ8W4oA)0LC7iHsYQb*u)bgnzzv$q`}J|a`7G_6tGUjNXM zJu|s=cFL(&9m?6cC*W%Y z78icEyGb!J?b~)Eb;u&sg+t~#vu|~bywCFEkY+<4BX`-XZfDxeW0aj9$fh=EVe@!1 zDALL0bi?;Tn?C3VQ7ItHMSKD>*;2%nx#~~b30$9Fnw)pI9?*{UpLe7_8^liIU;LHI zNW)j~HXk9}2h>SLMLtDZ)>TZ=kBk%&B&i;(%4~~qY+MVy)G%Zw!j>Fmpc%)<5~e3nk_6PR(l&7x4l{bMLG8$I!j=Z~(ohUzO3fvs}DkUx%I*4kq|w7o>?``m|d_TD>j zg~`x6YGgn1aHJcSf0P!McgZSrlH4;Bi9s9GxJjja9Z(yYE;**mEjLo>OdKDPZd&59 zzSanqUF+VI?&1Hf`b{;bWI5u+W5$#8wtDLYULeRFy|Cvg$m!wq_AJ`DQl>ywu$y1H z17MAC!VA>@y`xK=D}Btn(MqPlBzhRSXwiWqK&{+?ug`_2<2=GXL7|s6I%~fld(1bL zGZet#3{|A}!;WQxE!-)gUGi3c68_@H$vT9Z_JqyF-lNqbHm~t``&ZUXziIPBp?(3#&HJ-jpuzK0J}8TvqZ)V||3f-!qnzvd{^XJfSTj(kq#k7e7PII@MAqMM3}Y zYM8{Nf1I4s|(v;a>#OJikVD|-OPwpp}5_^B2)zOqW2}cvMhRW(|aY;jrw>*D5h!*x3 zRb#$d`ep&a?H(1dAiq_u{hlOD2)goZMZFDyH**>Mp_cT)8wceiqS3tLSa8 zq;g|TurKTLU+Zy6ylA_`vrS7ZqSQ$tjp0lp3?XrH}<>){|!F!B3fL&hg6Ce6uB-%f;*v@?o-Q*Mjl9 zDh}s!MJQpnVLTjl#$urG)#kt8=zYMNqRxPI9Pk=5^l?UxsnpY!QwLW&&hz22;&I8% zt|XE3XxL!nGPezVW% zy9vxioFk15Jn{QPXeTs7enPk()mCF=L(}l_kjBxer=-*n0&(t-Bj?Q_uIacf>7`XB z#CYlhvlUc^^h-fc68RcCqIlETIO6cg980y~zT;-}YbPJCSj|N(N!Oc*JL@f$(&iC{ z9RqP(x$W6)M&h#@{;0d!yqwYnxR)2=Vvk7smFOERh5UTRd)Uoh0w*uVQtT&Ynuw@S zr@AQWh1UFd6PHiicv^2d&bBu@31KtPJK#?rHVef7A87ZWW>gdVNrSN=H78^ee_uo> zDNN|Hd|B%J0y#&P!=Y3n^A7#I1C+v66lHLZNJ>M&QPdL%w9aC#g_Jbt zn#UPN6%5R|2pU5ezJ1lWKE_wqKRivINU|M7F%mnoUIFgUF0b z;6*o)4B|JuE2tZn^E#jdVxR%*yV7Um-jSn4r=0~Z#&$JQ}JE&P%pRZ<;a>w9{FN`N`_s9QWq+Br}poi0u5i*V>aDE@7QlCwNX#tZjUvm^z33Hr{z#xGbPK>P_i7w9_=Bm(yDZhNq4`h z%s!K4jo8fq$V4F{j84$&t$b4TUQoDR}YydOgZjsx^^JRM+bKe2nM-0@k z>HslTUu;rd%ItnVrvsows%+v;saHCKEigpZ@cWj_k;&4OJPOj*IetuDGsvR2Q?83V51RYO9agdM~sG>!anbhZPkkmDz$cm9#HJQ3g$p&aIQb87g-Jj3a08^QsN*N`GgiX&1Z=7`G#cnOmadk=w2}q5A#cPviIQDRm{tw1u8`u`N+oC zt@Ga_c}Rthv=xC|4*bdzTMoXm&VPd{7egG3lgfW7S?)I9;R0`chuH}!S}663r8YH@ z0$gxKsg+BS_F)o7`1Rv%#tpG6N*lePl5;yp>zH``gR&qfe!LaY?l-m1OZl0j|Sbo#^aT0EBx*$9-x-F{Y~lDf|u zskDMGsj8$;@jm~W$U&l|FoPy8sZ`>jUbXAyV4GBE!`wE6O}6QP@AF+Sm6`rP@$C8q z=oUcai9u5Q5Q`rpm=6&CD*6A)A^+i)|3xqVJGcBVdimeD<$EIW?Y0>eH&5R2)5`E7 z<$GtQ8DD_^GRey~4pNzjJE^{KWUH)HB#z@@o&$FFkLxyRaZGjsIYTb1g(I%)M=iSt zMu5o8J}TPgVM(Gvs=d1=^}YnDukV!9+?AqmYhm#Wr}JmU+}P-FNw)HGvZ7mj!l`Xv z0d=3az3NC60!y;>P+^W$hZI>MTgE^a%;a}1yQEEJpZotjL(`mwYT~~7OJ&K${eH<; z@$&u(FMd&UG$gbnWlff7tJsAJCZ8;(81QiTo=#J2iVgYf84x!&#j3?N9S$RIqJ^1I z*_`4O;=VNV&b*vCz;qrtDFZtp4QrlL!*(XPL*&eNwX8=ik{Xc+I!!5qlm6{HPR`a- zP-Wlpss}o+3mJ*ReG$!#T~L;DsDwu>?iL}H3l8&I?C6NePOVxzl!+W*SqooHbKFDY zv$L}}vuC*s#X%Nf52ae}1qpl&WLhy}b+wML4mmj9wATbLt@|BIMl$4C#s_bPUW z2&R;&n0G8oka>LrWs4d;i_2tcxPNo?sw)9i2TWVXi?b0T&cK-Y2rL}j%6=g&+>A@< zsuiX(ZLYU;O-xeVrb_WaHGa};il*~nZhJr^94Cw`S7xc5Zn>|{90Izx~FD|_e5R#rQm%j zU@;|e>6IHVDA7vWUx2hy>w+bYGUunDpDM_V z2u8OsGgN({Ggyim0na~sDXt`yrsc2of#SwP@5O;H6dK|38baT162qRS3o1nfk-jS~ zllDCA@X&qW$o)9ikw>ndAfcX{d$-F5POT{{!2F|CvSjH{_>B0-lBc_zi$U9hmq7#d zIwlJvwN&UNM!@}EV4U>uvZ9y;Y14jLkh-%cyOmQqs3sBBl=;mt4K&)(L1j)_vo@q$2j+`rUp9jb*(*I(1OUl&gmQT8NQw{Wq-n1iR)WJ^ zyB4VN0AR>x^shOUg|d}m7^d3``40F4xn(n1E+og@VSf?}8Jn#MJRxJ@e-f*jVmxD` z?2=lB6_Jb8%*xd`W!4sqqym~2jKaEf583t{U?}+e6~rBDU&5DEXl?=}d;CWXs_c!$ z!eloTe{GK?!LA3o zKDyetmq6Y|)EU3+g5h~!q;X*9frHwwXR+mz0)GNfI>?Dtu+gzj1vcr;|4XP4JMDg{Bi$5mSyJT;QA-#rpfvqb*_n$+ODC^1!$)Mr@+K%i|ez;i9Mr-i@Yoo6U8c z*V7+2iO()wV1dfe{|@$B+=T|PgdHxE?(kFDOpp5=qjkTz6-EoNr2!ccGVqq_d68y`VJZjwe))5;~Hj)4suR4 zKW)ij@$5Y2y<2w^%+|-qIT!5!GAP0Q5MH0I+tHZ>cLWJ$uX_6By_#AkgUE*AvC<{F zlqx$O8ZO!J{$Zh~koV!aG5-?!cD_&o5XJ`hEjmp`|D#3;s_*E9qxc_9>O=q}k$0N6 zDRpXdRy5skwa0I22fKG_vkH&gvrOKvM1hd{@dK^UaX?s9(DGq<@KZ zCIPZ<&-pm%h7x-Im9#`+{eQQ`J0-c8c<<2}P@-q5I0<%?%{AqKY2GFm8X`v@x|OJM z#yYP8d#kt3clPJxM1I=gk8$wMuCDVDAjKVsc4mtm;vcPj^Zu3cXBZdzv$P>>1k$vp znDy4Q#AIFO=9CEl@|rky;)=tqvym(FYNUY+M&{hFugYy@Ci@hC=u(@429Z*XaGrJ7 zc)&zU7W;=i7OFEzZojEAmzOJ-4A;S3Msz@AtT!J~xrNnxNRpopjLERS#j4g6$Neb3 zbTK#cdysr`7f1&4Jq#KmMGj?-*`6hj{!V0~leN#ZH7seeZ~H>~^*CWkq$1hphR(|~ zM>T=ggtny?MaJXsI8Pw)Z7Jn5X4ud&Ha3#Gyby`lhaJ9_VRf!K#SAj02PX$fDCUsZ zwVUebHJmHMlRYu5F0=R$h^q5y;QiNDVWb)#0@^yQ2io`Q;gzPXk7RTg>Lq#qVu-+s zaEnq7E!txP6X|3i0$6jBtI)mu0F}FFg}p5p!;WbQ2dh6_d$kFU}X*7R_I)l&%#MN)6Bv5e6^5pcLDTGD5n115Lwl& zLS$`6_L&v|Vj?z-8V%Ght=`ff zDEA5*QqgXr5{aQ%=)$qKmEQ?`goQH}cX)jGVBS-zji|Ry$}?TW>FfbB_g=L%GSs43 zS=Ld|UTY{``uDPfp|7?7f-n`- z%};=g!b;%%{R#P})n7TZ!0=0>efkT&mKJL%tV40~OBbh+iM~sB>O_pag#O)#j-c*7 zY1#x&sb`$`a0PsFl`gmmHG-XnQQeswNW9mvh}ZR?eyd?%*c)xBzS4YM@eW4prx`&J zqgNIVfzK}|FMi))gf^zjELtHb?gd+r_rCi#NGOR{hc4~K?!-5~WSuRmEI_YGzi$`F zu)BbODsjXR)>GXVwempgp6`J?T=8znRFhia3sf}$=IzY&y%ISkv-v)!qf`%Zx>|`0 zk>sd*m1AMFnBmOqDO55cM@`y%!U!JJiOxF6#SaE-mo3PZ$@3>lYJ+nPa8CkhuMe&M+-7*opvDyZepiG$5{_R%-DBTFNg6!O5}gad;gyl?0*S? z|C_1(HzDxe%?WPmM1C~*?qzQtYub&Sb=+xms59HC-}(Sxmm4viW|@ng`KFDyx+lf+ ztLqm$gVDi|(WDNs#I*Fh zE~b`fq3khTq?vK&@BmYVr)C8pE0c&*REV$n+?iWOl_%@c^`Vd-i$@M`kHp`%%4cQZ z$x7Pr$tPO&ak8K{(tJk)_1Vej6(7Yqx`^**Pj*VXA|H*?9OdP{mZ!NBDq7A}7od3& zie7URx^B*{1rz#d^cd((REQ%3CD_IfnNU?&n19OBn6UeK=eQGc9GXd51+~7D`^^KLP?T+ihI!-aL+1TYv;Uz6|6ASv(d_@N2LG36{Cu%=VpTyi^U=Bi>AQkQBMN2}>Qh(u73L=ZNeEJU~N zb-AudPu$6)1~!=m+L=Buyo!Cy4PV=sA+J;b!208?82WVk%3QuYOtyvJwqc%8Y7_^qsux2bhr zC2btV53fb(cC#hAzUAL|6HwF!%~4_o$#L*H1`x+|+%!gTMKc9o1)phC+Xp>k|N7D_ zG>o}3{`C2EX@ZkeSI&^_(M}-FGyNP59SMw60XRBK@Ql8Ff zJxJ~oajcoOALtyeWhgzY29K(TRTr?DBcX@J=vmUW`A97gb5+Z}3QkF<@uBbRAG#gD zS|tfztUSLJ^i6eDe;MrcVALw~hMOiXcILMP1kzPKP6c{fNcVQ3F+?-fczh#TI5e^f zGN7P*v0G@-j3e8e^dbD3-e)yx^+7RcX=*AiO0l*oqsMW zaS#o^hHGd;Xh?83b$J69qqU>v%0X_8YQT^2szrX;95a&|owJW#o=oo6e2v$LdgdT^ zjnr)EAJcJlC#Gr}qfO2yU;2GF%J1jitKT!DWAXmE&`7lAu|x$Fz|WTmWw7MMZgQ53NIUTw-+90z@aBdA5mdS z%PWK9v61L8Q2y(mOa#` zg^rDcR~ddI3n7z5Z+o``82^n?lJq3{D?J5gQLIP&EIz>>$)U9Ft$E8WrL%`Y4D>E= z>|C0^x67zZy>1y4{`#fl)S7pv&iTR9DDpOv-6Wf>nv2+~E@~zQ;a0=RSJITQnTAd1 z8`Vta^_al5Z3`>7X3f#h%E{dwtsq^A@ficng`ZdJiJgyxJ{v2G-prqrpO-%XmzHPJ zN#Ot$+K-C*17Tp^n1umFMM`NEbAAJdK@P-RYW!*JaYRP3DIV|e_rsWfQS@Oe`W{8O z8SNiSzpfm#t%jKpy343b6DJPCvTcMZYS9B#*dx&_X}sZg@cExg8Q!Cd`O<$uW>iTo z$wJ6ZXJWI1;d!j3OshLx_~OA-6|C!c5?7w!&u=(;nx8ihzNjQvYBk&8;UMI{dtn%i z3Y!AKy3`cbP{u@1Ih|zVqU&Pk$!5MK7Pvro#qD5;*&DaQOC+_@8KzbgV&o}(W%|g$dv`1iQ9lA@5i?}x3?4EGwF@8Xi-TN zPN`2tXc4GK?AqCO(ejq_Xa3BLjC|=ISt0z8)iYp^81U6jRlQX_sJhlsZ{OVHYGZhM zOPNd;L+l6vAJ#;kz$w0r4}Kr5X3LJJcG%yPv>hQeWrz`^kiPEQD#gkJwXAHY-3SkQbDV`w}oy^>x zKr-gtW?Mpf05ZF6Vo{i^VMr^l5Mo>r>CF%FE<*_c=@FWydN^t8apJcJ(vRr5}MSJ+S7Dv*nLU4$U*JOuNy*REH6(gib^mtF2(CMSeGQ0E4 z#4PYlH3d|De4&n-MtoZq|8vw0%HGiK;ztM3#l*vwm3=is`Crq;vJ7h4j*j>;vPGs7 zhQC>|t%8hdjyM?n&}p_8@MV#%qWZ=EJOOFe59w|~s(mQQS$)jWM8ED-%#<^?*_Cd{ z6How}BqlGhq5^+bZIcIrWa_2}0fPe0B#C{asCw_Aes9eH#0oauQo3wXSXgDJXTYqS z5V?x}fPirFlRTUOtJ{=Ejj!t*MUu{jC1r@6@v8J#6GtB&tad8CbXOfd7zaPJ54%7nfB6!_+ox8H=&PbxkSY;*3M{*N{VJy`a_DiK>S@D91SPBRoa0$TRR&dtmfVxX zUbghGB6d-@U!!K-vBV!v>(WQ)>t44XP^|UjH^YQM0o*=N!xG9gck=M4#xXWDQw}h- z=lrC!i{XtD_5lD*F*tgniUbrj|H#)B;K`e{`Ay``p+3}DUctSp^rUxdd0Ke*#l9@n zW*Bw|U*Y+^ga*j{3nwM|sgEoqBm$PVl%J4ou+O7Il~x8WAbNtQm*Up~@bhp19B*ig zZ7Q&NoOxXIRTAOI@~2{gP?Cs!B=4E_+Mk$yoPNSnF;4{85T+VBh}&md=KdHdiEl9V zMO@6HSxS;zjAnqo^I$ z+iSgAZNifQA(3MkfFOn*!O+c(Z8c5D@Li0DUH2X-irbgH?g#2W(JpbryyqD?X`iew+=MSy+yja6R#qVFkejtj=$1J3Rvjc9&aQdp#pj=jcH1{ikz960?=LP2!e@@jkui zVt_CmSNT}K?{`v<7%t(L!Cmc9pO}3~SR+=#=rr@fR;x{Zg^Fwn3Umqz#GL{_7~mOx zrJV;&FL=LAoa5cInZWs%9m_@%uaSyY4!;Mo`wQAQsAtJU(RlBC)dRMdq};)UEnjDYKL*-8nmXALA|(1OP*@nHz`7 z57bPj?K8eI{&x$hJK^>M?oYIxWhIW8S;W{i<&8AWsZM}}g@;FC>ze<%SrBHh=jJR@ z1G>Z(XV_0&$v1zGh`j(&Qnbgd4e_?QJ30xP!n*~)UO{dnT@#B` zE7pL#F{vLPoJH8$F*}%qnuRsd?=7I$dz)TFd*KTrJSX@mMhoR4t@Ttb9 zWogC-i{ief%OaS=h32O%RI`fy!dq49qyXklth$bPYn!tB@SUstD`N_90mTCWUZ2bg ztJ`Y2g?X_eAPcQ~{r&wF`<+}4w{RJKVu-+~zTwZOBe$$^@^uy)7+Zo-!r5m3WNfK? zUi{he+xnJq^P|Hzo1&&Sr!aIAQ(GqK;NL$T+n_xr?mxL@op*j9o|ZLNfXx)p%b4tR zIYcOZEpD1nepiBxEbB7d@zsk2<3P8lo1jc)tlE>L_Lw@}XByU9aC-@2R4(piMF6{w7$k;*U0o zWqw?*g$9J-U{)=on~m2TiYJQd&v$lS`7UqG7pMgdwwoJq+uCk?<}i;_ zY>gywrDBMQk`%+6?tUJ*e$OCtx3T>Sz{2R``@?sH7#ZzMK#{Ez-(KHN+%|Qp>(7A_ z(+vm!)dLtN@T_?@<4t?KQ6ncV;tV_WzbWNu6`As#ggQvva(85crk9AO1lWf;W`!se zEqs4kpp!0u2*u@VraoZjRbDar59+hGx+kKl$FJqIIJ;ggs7-QG+V~Q>OcpPHamoOi zFvI4^}R@XZ5MudR!~VQDRaqY^uime8q~EQhZi3 z{cKzJ;?|fdWk%o0ItcK0OeeJeA#_Eq(qHu}5jKbKUH`yQa~v19#?Xk~!;lp4?LMwf z&Ed`A%XK05+odpB`@Pw$pYL_~o782Yu2797U*0&x6a)@G^dLz?AUz{*wIsoA z%~u_zD{HQ#z=YhT^kuQsk^rtYRxB{Ph~s)WoCD1<{blT0%s$VPhi zTR;xJ$qpBWi{ENmy2rt3lW1;|+d>75i=G-(>Phy8if*55gHp6KQx}d}kxZ5)VltFaghS)cyy4k2^!pojd#n~g#GvU9=90REIfw^_*XrK)t6OR=2h1^hO;~P~ zD@dd5IQ0)L;5dsnbZFCjA2?`*UZ`ZDp^P}A{Zr3>$ez))s$2q zg~tm$+c-eqObYFrUaCZxS4g4J0-82BKR>U;IuVNnBg=C z8=zUjwon54qdHY9>joLMNT^UupR6?U`K9Szx+;ykrX&ZG3y7F0q4 z8f5Qim(R2FqGfgjEK9ep{Ru1MQr>fsF{F=4E@KFvD#l=$$C*!$zr63rsoBy$>AD=*&0v{c-Mc|KM&Q|;K(<2+5sZss2?a-vDlL^B3V z@I*4l1`B~(Qr@bq<&TBJFMb^z1FXU|rA_pe`P_iYZAgJ%|G~M!T$z?Qwn4$5;Mjg9zyhg2pmX1EOjtwVcmvg$9Zqiw!Yauk* zIv@?|9g}#HT_D8_yb~Mf@iJ>}(NCk(*~-X^-;m%Zvwp^MCyqI@A8k?inj^Mpim8=d z9sVpMGsk*$SS2{Dy2+*QD7whQS`k*{-Mzt{ZntZ4 z6d-W0{+MjapCM?|fiFG~)5&Q*xQSff)n#Q_rm7n|$ODtb1`Klz1lnS_B3m`=c*g*+ zYzF^94C1`|rBlLZa-Mh8r&ay8S9g4P{o;->76AD1&dhIoHE2ti@J;odspxE>ar0hd zT+a#efJ5TeFHU=*RN6!rf%p$V?gKjz57rUzpd)56XCvnu@jvu3W7kN}Hbs15fn(;k zXL&zqkL-{tdA3>rpZ1+~K41L6^QY+3$*tr02j@&7Pzx6m1KQ1`0XJ+t0ZQEnHEz`T zQWLQ6*q8IY;9NxTY*cOdmM^VO1blVh@#CT3r0)6B^Q8&%3uK|Fd*p{XYG+AKLno`Xa&XvQ0Cev9YM%q>^#lsR2?7O!)S&q-UdL#vOGO-d<1rsUnV>B%{#P@#4isD_wfFlut1*|@! zk2itSZJ+x|!{X<5GRDOb&757lZWWx>SVy{_b3c09IsM3(`q<9O8`TUn(aahuNRJhl zvglL+B;h53D8xN#w#@EP0<$xY_qOVLd;YAp`Iv!b#I-dHGA;o~>u%TDVfBm`fZE#k zvs^54lB3?DQ95XBgX!<~zRod#QB%Q^@KRG&^Eg+*q<7}--c$?a_90Wu2%I@K%$B>^ zQ`z#C9d=&ZL3H$4%tUqh%EAxl65oZ86_l0Qb?K}pf0MfZkb^P6llFWI&yt%38|WUn zy&C6tV9ECfAu9lYOKkUiDqq|M&V{qij5dt6k;ps7!9lXnVYB=Lr~~{?QMm&gPoJSm%JlYGf=Xd zAO?4|)FsXZX2PODYl)dWx~G&&CF7hO*l!~Fe8ysX9YamZk#My0Qq}ePj0=x87Y%>J zPHnTE(Nb2K*P+w#xpr;Jiedo{=y!+17SD>u6*L3Lb1*f&2&ls z9MyzR8G#q$l^d0d5zA;cT)peQ#v9aXYNadsDKeiOA60h&{O~htyTK&Y$x2I0T?MBm}i!{7rUr4=&a*d>&6H-~BZ zl=X>WEB^1}^H!}C@KbH?Xn#;!4Oiwrw?dm)I|(qSisi$5!Uw_`}h1uvx^wm z9JH98gid4hB7%$n_-J-$!t0i-?{()zDJhqRm$o(Tg_>(p0q;>KVME%u^RnOBqnQzA zIS0S<^P^&5v~cX4RtH>HkQ|kixJ_|(GvPu0z=a{nXs;60NB8&XeD{eq;FyPT{3f`W zOCgF0q+&baGig~-^ek6>1sWN_gD_FZt zBh{bz1MOQ&K9OdkZx8s87~zgpYNP9VZkBLNDezs>uT@fygwjnMt^Igm z>(M-axv(-~V5Z=SfLm_lX}jfOBw_VlQR3>UT;KlAM>hON5lrG zuDN3&XDD)XqPQ)%jWp!0fN;ft)CdtHrXlIRafpI~!k<537?Xl>|K3yHW&+nc=Hz{? z5)LRwaSJOr6fS~yKloMvb|*{=RuJ`IIHpf|POMJ64vTw-P*5;%ah3DvfNryPk}IgO zp>OH=j+=zkz~SlezBIyJL}1?vD$$3k^!pJ9YBl0kPSvz6k}&`M-rf^7^9_*i+iIhi z{fh3T>Tmw^TPwtrdQ92<0Cv~R zyd)vKor%_tR4ic^WbQ2c967>OTC>qJ@-9lc(?1ADE8^wb4~cu zDMI}ogR>Z94!w{xk0nYqb!_>1!B&nQN)8MM`8=W2C2*O=J$_EF&@Vr2<3y<~Sl=4U(MUiAQe4e<$kL7mwTSS*_)PpczAk@`hk zcN4{tc?z<-W{<0x%wFAm+0aOvdG4quke?`>4msUnQg2Gv>BS{R+u=?kibZwc%JQig zjdrVM7AYHEOyJ_jjm-xxoTGHWYh)3<#@d{#6V<$m4TJ*3o)aM#ug4S`#svM3_M=R+edx-+O`GSu`%*v`{UYZP1vsN-g(Ge@u5Tn|Y&; zQ3Do!C@*f_cem)*Jp(H~W3}zcm96-rgs`BJxv zh-UZG*TS?XbDV|H!jkF{!-@!jR74If2p6h`T+$rdXh3vhs^;*)UV`Su>}9g-g|p5P6=92( zkCad*8uA7kQ}e2M@;}zX<=Kfj(IpwOWjgut>b?v~@88ClUQ?f#fYuKTmWjsIsz1if zwHXV^9`~}|Fc)ugTo%@IhZmjGe$gi}j2*zTQCA@PNXyQI11hxKzg--^H&||SG{&=v z68)xVctsiSy-;awtK2z8tZgOfkx&u;>v8Ot5m4wYWyXyo!%RI5;W_QG2xHQemAmB5|hWx+tI^CzY^jd45a@oVhGv{(y(`(bLSg#ln)&~K9Jw7kest-nCzc2xH5ww=R8xs@z+&=8n>dy$8eY2XzCCyQeRJLU9gPUOHT&^3xmZgN2{4Di>=zu`fDy z*+U7y#og&m(i&64euJm&RtOT3J&r4c*re1vrc?Y1foi6+U@}-FCaSr>Q00E1@;;}R zFCB|&onl#yT+O!HH=(3iuX_9N+?DaST-iBF0TkfelfdWq#h9mV-dq8{BpZ~dpHxvq z>Pv^@M5loHIQRt1eJ69mV8UiWomEo~?f~wx0J`NUh%fggNHc+XH1|@JtKqxf9n}=! zp&^!!ND@}Hi_ua^A=m$@xn#Hq>XC|EF(VQgU-nzy!HsR|dL8#;#xq@e6v!{<4@#z} zcGGh3pSe4LYtrQ;+O&DiLgJ7aUc&mg(W^~ccGySNFwrTgFwvB>^D3HD8`b9~#wX{a zzFIY%uWP>xy1WE%PhulsUk9m1{TFmOgTCsU@x@mR^`LPI_F~a}*LwR4j11ptT6;e2 z@Px}1r-t`fx&G-YuX@SBLvm(=a)>0ZyN)565*aF+#krxQY3&7}?)M9l>SO{mgry3* zMnU;KA;vdBc|36+Gf*;Vw|vPaZ~4)el^wWn*{?pe0o5PzJxbmTb~^X|O0aX5B|@5f zpHeq81Nm*Ck$wo`JFxRvQofsM=IHt*i%K)Z9{U#jYZ@<76~&*~FkrR{m)#Un$B)zxDt=S( zX~DEORH71x2zJzA-ZA~ea5!O|;iZc3f&7C_A!Qg$X(NS7M zRMoy3psD|Xj_rl4ZmPY~;>*lDQG3_c9J0E{3U7`+INL?g>=ehnFjIRkyoXhNr4?5o$u!UGGCsx9sMcPUU^p z5j0L)WV`dYO1aPVXGr0R=kShHUuDC3o(W4CAO}pnDAn(%QDiKniTsq|AtQLA`K}LH z%WFSw8z7Sjp5egTg*z*`I&(hnyVM8LZEkZ< z_RO`4HD5%p^Gk(VLh6Cn3_Dk*WAa;$Z2;GJ4Q<R)bw9_uPLs{Kz;<~jkg9W0}^h`BSbwo9m>b!?bcI$hQ3t-MEm>!^`%rCgc~C8N2>?IJk?jHLO}3oPir42EfcWZ^6CO52~|`%V{44n z?4|XFW zU;14S<}Q%^gq$PG7w6Ei)nXG4Qs3v$z1`NFUeNDJ_A@_Su_nwH+^}YZuC2{3#tjG( zfAte<6VMDdCtwe`#gz-%2euYb?Af(xu(La`+6?mBMyq91al^u!$QVeoAsjIb$!fH9 zW4<5LyBz5qN_vxa&&r@WYDlYCpP%m`xqkE5cpH;N(1JJCm_+1ntyb*Gb_N*#T15No zE8paXi2B(oC!K1C!1YC?(C64;21e;s=;59*x(*ii7mD$1f7&v0KO`I38&P9+*5Aeg zU+9t_=-mb>{2{@XiSP6H)0@;@`c5662X~*>2~KZ1;nVBi@TgbGQhRWvRbJxgUJp}1 z`y==sIa-?8em8T0tm+V2&p3=E;{zXta=h!$yhJ!2{7%oG|NY;y58UCdrsm$6yv_Zd z!8~Nac1)p_Yo<+~nq{^CyJWhRv08EfnOH^F$-=tSi3E=0@`GdgqsJJd>x04cmk&2* z&Ru&1r*KFK2n|^W37qolN$G_>tbTvbpg@*bZs=AJFkuZx*W-=9nbrfFphrE%OtRa@ z^ed0nWBCZkddWR*H(VllNBh0ZodE)I_ngOQrpVvapf~Nk+3=FCNtN4+R6%lajdP+} z@ARyrp=@G>Y*lA3<1bOr)BB0eEjUudA$MZ5+(izJm4H1D77P#j*)~k8X8MiQJstV$ z8W}Bwb0B%V@tn-vyZL^-t}<@@yOyJNOfmu*noKi1~i)S_jO9C0j4%V$nf z`v|tN+Fi~U0Bh(m!2%o3pw&FsMaorUG;L!$V7ARUf3{pBjvduri82rC`uP_KJ35fL zQ2#GszKfYrTaCs2sEuGkYV>GG=5_SNVtE8sbq2LC!BjM>$srSo0GT&rY})n(l3zfu z;1{07DWLH;)h2VFBTx`X6k0OrLm~P}uOO>XM^&09!|>O*2i=;W!Z=sx0Lp z-_tDwtz)1qD_c+4TPOlt{9Op{7YKnvwxHb#@UCVPC&!R0dtnb8qY}s_E!sxV{Rg$$ zd;cb1T|?SYHv`6ziTTFSo2_mqC}@=55EAju&`4u2T-WMIyUR@V2N%1y6V}c2$;aX% zo<0^!+tF*eDwkU=W4_kDu`Xz)zdMO9B|^UJ>P51c_LECp*k!kYdnZ6au;lwexMpk1 zzn~>*cYD*3KUd1%KgNi4#CY!_TuKqkSb0SaltMShQ<%__xm27cf?ilgb+LeDrcrVC z5xTZCW-G)?7*}C5x5Ic>;w+5bd>Ig(3K7n*k>c=YZ2vm0E=Sp~-jzU9U+MFV1nq%yxl`p2E8fnX5o1CiFrVAH~t-2%vzDJJR=2PMpPx(L;jc1%Za^3;9qc8$#1` zPniQWbRE|cwA=3<>MIi8Pw6#A`Hv(*R?h!u-22B7I%WTQyF&9l@3JATv{r=1tYZ21 z9{F065eZ(Q?uQvQAdKyCg-Wu~UZROAac16ZLo|hl>lIRZ@`N&aG1OqS$Y6|tH9!1M zCEvn}x11Fy>X4DM0%Hn{F2Qreua}op<@Q8Q-m`;sIx9+7jEIDk9PqSX#Y7PZqu0w| zdyEtf7M}>h!FVycb0zm|6b5bzOoOCh%1X=#6XVETB!c}KqX$1RN7g&?|B@Z)nA6|9 z7r$9HX&)(twzIG@ufB#ds=aGK^laEb6c!QdCpnz$8G-ec>DZBy>{=?q>}N5u>j$K= z?R-l&1zy7dOLKe{Zm%&ZYCerX@x4@z7Yf;Wiwy^hd_!i9-sTEA3+4%`=d@H5K=i|`0n3?v znTKI8gCwz(szGm;E=iuCFS@}U#8KBD#Ig7*J?6hS9gc#Uz!=Dj&Tq$wv zqM4RiM)BdCTRFB86bsG0nedwMQZG`ev!@EoQrwhTMQ!aJ21CEX2cE7#fnaH+VBd@hiv3lm#q zc;ihfoze4SxGfLE+KjMwIq+Kwt)T5Tzb*?=q-c^uFo>$bEI;fS#r?Z2`_@%iIOei6 zd<7q%`+ZfwXPd@pFE|sAE&}prrvcT@HF{DfA9&CQ$9)56SAJbsm`F&hCsI(tpTwMATmk%%_VlufjPOJnY)P&AEE6`qCrkOPl)ifqsvH(x7auD}3a zIcmP+Sx>y;*jCz=np=w&n`(Coy@TgXcwQ?+xt9u(6Ug9cP#?z9kaUZB$y&DY=QV${$LyCW-Zt_*u z5!I2YW`z%7&ep_d6MGpKgJnS@-yXA?OrrUVd6IVQ#$MI!foxqT%cnlF$rn;%4)Wg; zd=A+2#aGKGALoNS_WQ_sa*HY4#Id3Io}WpGLRgALo5LPr+8*b4z{T5fGiZ5FcC+I) zYqz!akUdI^OeG=}^w(+iKmWd*|6O?@D!%J!s$F}j=b<&hO_F47BIAhm7u0@T@ zFn#lRp0A!xRk{hci+s{~bzgNy!@NIq*1*d6ATH5sfpN$EL!g-L)1b+qT~dd`73ziE zrbSs=#>rW6G>IcgUh)Aa$-U*l+;mgZ(rSP4626p8=cGxNB&bLv)M@u^RvNGncz{EG zlJ4O)*G+Giu5mtfOknRq%VT^a^P+MF(2OH}oy?isCX+7LKLU8!2kl|!c>7vf3o}Rz z*m1{okXDi>YyHUrZRo-8Y-2J^Lm*pXes41|oqNLeS!Va>qn1h?HRYPAQA5ng@VcX%R3+(7&&4L|x4aBB zzd4onUOWLq@zm6v=;Yw&P__5zydd|U7*>3%MK`|Ylw_V^7s=HzSfx%Fwm1}`tk`h5 zBsfkr{MYe*OJP(2ZQAc)HW5D)D~KFXocyS@x!S_N;W9g55T}euL%F~GJUj*-lqVxoA7ZZ@b4DKb$SB^K*`Jn41wy$j zvIAL011S4(+UIeHYZA76UQtvDO%d)W*>pZ!FXGoJctMIqPzwOG*?JJO7!UiNWf9=A zwtO97`J>-2N?B+7v{TaEUz47p%*1Q}z|Sa;0m8RL+TbyQR7sV$_} z6klIjvyZX6h>mLLI7$LJ1aM>;mmc2)?qX7ZR7kt6#P-BzP_jmSb=6}&a*k3aW9u|z zNE6GzYeM%C%Zd6#DcCRPZy*4F447wue?k98yu<-8nLov;h02uNEbp|>NE5$h^lVEm@phB{r4q_1*baD}3%n82T3lCd>O zyFQXIPf^j1`32T(neqNhfMTy7f@4$kA%7x|#;BXbfm9g9rwIk6VSF1H5ANAvO6sRl zStF#E>p16fyQDvPOUOVXbx^6neDIx@tD+1`=2@V=_>K||vuQ^1E|#G4>iBZiLngpP zRYSycL~BgQZmvmA=~g*QOD>qxBLaIlRC2ol^=vB{1MS-czLIQGG;lkPQr;F@SKvfN z%5r`7^+9w=D4oG8_=T2tDWWQ)9r(dXpkPS{k=*VQcjNXFNK{fBkwA(X%xDb9#%_2T zuk@Txm#&Ekg=$~H+e^igp4h5vZ*#Gi&iBGSN>{D_ zl%Hh-8S}yk@x?>t)Qz#8Z{!|s=vlecFSh`UY-kkt^j%Ucotm9b zD@@HnFmJ?wy>_PkOHPL1hi}fp^IS{~5%L*wN#saA4_sHf zEzQDc?RX~ymS5FZ;GweR5Yk5Wa`L&F>CIe<%qS-<7LL4GtUC-XP|-Dmt7(m5)EKmu2a z!)8@EN*6MLjb6SFX0CJ5K$jvy%wCPj#O`Gr=UQ)+?cfQ9iF!DxA}SzQdUDe!Ho?Ra zV+k$!d5vBIHk_cLRl%ClznuWAT(18Vjc9Ml=t_<2sS-Teie1D^rBYd-fw7SjpfM)oC>;IHvwdK_1CU3ItixQckwlqevM8# z6TOxdi>BGse+C)w7zYX-VJz&ut#tw)ozI*yk59)@+h7BGKF75R!d4rTpM(8E`y5Ub zWy|<697Vd!`ofXkuGC4~YV>*3*}vz;FS27XT`zYkpWmv}gVX2WKE=>2uESI3tM?zQ zbS~pzR;pWnnK`KNtQ43*HHFolhLGGxYA)QxfUsyxE~>c2}J|D|E{&jFV=cT@FR z_fx`ou*70ps z(J^(t94B+wyD4^B9bV0Nw$IaW(pA6LI><+52!>vTTLs z{(_rn)qog~Ej<@ea3%*tR}JsL%RBZZh0M^oaX;$e_(-B}w4_ohsr&y#z`bJVM@rxk ztbMjqlAPY$egmN^ooXx=Xt8)pt29)$w}-OeYH&5ioRC0^!!0lu7uASj2PZAExAC!m z=g_OY055;A?A~9F&Q=iQ{`@qqWhYGmJNy7p5AUEolKvM_?zZHkxy*4qey=NsXiCnb zy358vnmE85QCW)D{t8T5 z6@1IK8P;hd){`wacT1>vh0NlZnOK~0N3JhfU7n}jaW@@(_F^SY16NumZsOX%gGqn^ z2>}{E(Pg0YYHschJlEx84wud?W+&N~hWTXfy_(2`qbHM{Y`P>h-XCac*r&WArFp?mD?fAF#2xk(cJqto?7uD3pOFm$M?4&Z(1xImy|YN zgR5fsnqa7xui71Z%hGRs4OGfT`F|!Zt$*Zh%jn&zAP5UKsOj7Fw6HQ|hf2~rXr5-M ze&TT+%v(UQ_2hrLnqND?=5lH$$M&lmRuGI-6sZj8;|W;qV+pxd9r5*kz4J|kIZL(X zCZbw>Nrbtdwe%3{>T9WruUeSknM~+7e{(5k&it{+?}=@<6%e&9hJDM-XB>4_bKg3T zu@ACfqa1Kn>Dx?SSt2t2w_R^oG2c9qwF;kX@CRR?7N{>#Ag&Q@I>X!|JKmWFf*l6= z2yAquuZG|=KpUE~vO=>?ZwhwMPRj+IcRks)2ugW{HAWW<0-wg(szz-L)kMaEE#D9F z69Gi}==nIpwzsVIkszLc-W$3@st@xH>cfiv-&Mlj&DGtH=T@d}l z{LW9RC9knFh!}DA5d||U-uTt^g7gls(4WYdFTTQ+RI1bcyreOF=7c_9&D8XA_D`)0 z&GSTyKtuRnBnp$i`Re+rv7FmTe~zdA_!B*!m;bqG`nJOu5&5O%cr`WN_k3!2pv)IT3)d?E2H$o}V^b|2^BpYMzkps205=zJVna@$5(r^6I#UIbmsHUcjl`CU) zrP1D}7^Z7zzPxH+eXr^NbFJ6tWg-!-v}zm)dQv!kJxVl37ghHCnWdpIP%|6OHb>Gx9D%3cSiStSrM0skw8I?2f;bAqHSXqhXsdiZ#KUu zg;P1OYBXk(cKi`^15<>Z_gUHd`Ri0_sg=KE7*wy^*G*#BNHC+yCF)!FXj0uLVrqrJ zmR`x}TFJmtml%s&w>MJbrJqb@*K}R=BKK%ajhORQ;_h-UYXe4q)iu@z9F2~#<9M@0 zK>I=3n?fRw3z(0iA$XD@(y5p{k*8l+Pwp7r<@vg;rQ^Ml`8;sT0>oN;l&S;{^!r3= z1Vex4EqFvXFoWL>Lk)fqFgK1WP7J>uv)_BipG!kH;4Asc$i7{y=#C*vR~xC51QiLY zwc?*i#aK6fJDM!8Kd9(=a=64pS!)Xh0Ana|auU1AVlV)-CokG6$ z1n;RdAB$`am{PsIoPwZBSGy9!Ro1pqfXfdnNp8_soig$YimevRiC0*&nyTZB`>Sq1 zg_W)r)M}`2bvQ#^b2p7rYCsE?O}0Y|2%XQy6%CYV`O|JREaxXFMmhw-w5p@jE~0rU zRQr{-sclxz=uewx$*a>oqFreqNCqW&vqQ5`Kt)hPwV1^kd%G(SP^5Ll`&D;_wOMEM zp0&3PNwA5%pC%GK+kT>Pb zk9jOEB%dx>TzE`&BiJn|J9#vF$l7M>@-r?WOU4pk$V3xI{Ae=VM+9kA_V0#BTWPl7 zW)R_KJ7Qt2wFpXPi`GCS-t*zT{ttKYU)KM29PQ^*=i#fWOlJ>`Y}R36ef_&AXmZu^ ze`s@;nf97CdM_2QX5_gTZpZzu%WX)0-PR0WC-?6{q~%&V)rCSQ zf9^K~ld)ZFC+pHFswOiKs0?)~Ty0Sz&R$ONUx$vwv54!o`)pS6f4QZwPTRtZaqp=vh{BWl^XnU%_A6qliHWPEQZgGKwvh4n$#NXb%BkRup&-|sI zg3xI%pkHUd`_ANzIc>?plDaxDUleR!GFLQ5?tM0SQ$VTvCsd{9@}#`=`3%$2v3KzT4BEFkprGfVNN|19|;etXR! zFEJ#|N@-j#^c#Pt;}l+o6%esOpVtF6=6fgh?9=AvSEqIKI$iwtn7C7z+l0lffHreU z%9rQ9Z4db&<8jXB&uq=d{7PjBD)Y7n#A9sYR!zPlba&o(zGdnOf7qnd>W?@yUpTzp zBdz>O*w_&#Ma%;Y(^V)Y*BZrRP(9ZetTFx)Ph>Xaz?2=W3DH!*YE*-i3j$z6(3zR1 z4+hNJv!U9Bnv+qS{aQZ>Vkv}f&*|P`EKcfD9JhQH@?1VwjS-^vk8b4Ri}dU^dkTY~ zAuAjt5EwYb6gW1t+pG=fZ)`=MmWyeuRk`K4^adgyHl73rN= zF>|t!Yma&3c2JtOG&N}94-BeLc2#EayH1wxaYCZ19MN6?&(**(ump+OyO3bs>_h zmD09QcH&HWaw@dL5bp^*(Z3G0~!y$MCW~b--E$H)b?Q&**!u7^fWAriL`<*Co~q zLzjO#$D>(DD3<=*+?ImYmpef`as~wuT3XIlNTDQC7@^7ZaB?%76Yl_Sa~){qz40d6 zElM;+yUy>a$wkkOXC&iGLxb)zugSgRw)Ls0pC2V3L)vB}Z4i#c=R|mld`{M(N+!~r z53*pf%*{b(v69Bjp&M1Uzk}6z?vJ|(o=$_!ZJ*f|`b7rxNOMppbdD9wVA0fXs!*E+ zTsLUzziqkNeN&>wrC2u|#%U8&#|v&~P|2_mKxSvn7paqIwjY}&#Vdy}t@rTs>}^w* zV5X}#HlJ-9)k}>geLTlS05?f6wbR;m+VI~}U`L{@{*cnNM@!>LvAXvlo(OkQDYt(= zpgFJMj}e-)r_{biEjkohknqk~n+Euo!a;A^hmAd(!mxS&jw%SdjZ&j%dw&A|NaJbU zTx$J$&2!&4(!2K3 zf4@`GqkWO9jkKF;sm=*NpmtynjsupLU47_-V3bIMf4%m^Dg#!Q`EKay?Dt;wP#Yz3 zOz-wcH6OEMnrB$sp4&+aelf0=Tk+A<$+y5<9iTq{jJ3fWt9{p8SjQgjd5}JeQ^7FTx#kSETE|(A{{1KC8YOVWlPE{B|+24uXg9xQJm9 zIa+hmW&H=xQ&+rO_8@ug^j9si27SDg$qC87N8@+tCv)BtPy&|CrQbRA*)N|P`JC^L zP0aoj30r3UkFowg%LNHA06QG|PvP(%79u=N`1f!BSpShQ{Fn7leewUM4$ALEBEipj zGs0v)j|=>i)9m=hh}?9uf1n6(Oo;);TO6;AuEtR-zgRAh1PfZ#S$V7%`u%I1wQo?N zAA7HiBlv!uEs8TN;bgplb%Ru8FE%3_d}!#oe#ZpN=0~OXx8syZf&t@iGiZ6PnpL}x zcBW7+_&cvd+T6|Bo|@Thm(cix;<{wHqLYRm0epD7QBZWecxda7+)-#wGJtw zkH=DE0kIBW;Q0=03`DZzyVUfYP31X~>ekA_e)7HyW&ylzy#ty*xWgMlwE#y!ezgv% zQQE%_x}|+2Z;n&tXtFXFm2WF=cdsfhV4seqv)i}7=$&@5ayYu41bBd`)fLyBHg^q#vkUC8$=~h;Na=w;z&+P(g{MV>me7Nq;e+?; z{fDrL?C8$LmRT#0Qn1nH8*$6$>FkF^IaR|?E>uUMO>U!D@FA$c9_kMM-me#rk7wrvr}>W*iTjEDM27r;i;?+=#+m(~UXki0 zrbV>1EWfU=6|8F^T;~nX7VlZ^L4K+oiNYYY_0GDPFP(3|_kgd>S@~n>vBDLQPQD!H zof*#uz@eM!Rn($#8WmrZAC*&5GcTJvL3o02BzTY% zaEQ7%yuTcA`UBfuVqBvkaD}pe-RuXR%A&uOu(^7LBjTDXv)eyg90J8bKv{KnH!2=- z $+zD_^tFe+}EIlj`#a>?36DRow(SmTQ_c2Ay))y)N>!56Oz9NXR3`eTh0z7n3_ zpsm_ha0AhV`}yEXC;}QRmk9mXl{q0@XjBCw^Zoa$SjC_6b5jQFm3%V?ygFfWF9K%4 zm%xW_GS*_{sN$b@-IdQ%=Xs3vYnFsW8W!Iqx&Ax)aIs2bZ*X`-% d3korU;VtUrun2`T{G(_H3NotFm69gk{ulb~(W?Le From 37342c89ca959f962d121adc74b17e63161c4133 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Mon, 22 Oct 2018 21:10:12 -0600 Subject: [PATCH 21/22] More readme/header tweaks --- readme.txt | 4 ++-- simple-local-avatars.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index f3d95831..029ad175 100644 --- a/readme.txt +++ b/readme.txt @@ -1,9 +1,9 @@ === Simple Local Avatars === Contributors: jakemgold, 10up, thinkoomph -Donate link: http://10up.com/plugins/simple-local-avatars-wordpress/ +Donate link: https://10up.com/plugins/simple-local-avatars-wordpress/ Tags: avatar, gravatar, user photos, users, profile Requires at least: 4.6 -Tested up to: 3.6 +Tested up to: 4.9.8 Stable tag: 2.1 Text Domain: simple-local-avatars diff --git a/simple-local-avatars.php b/simple-local-avatars.php index 47685e2a..bf0cd5d7 100644 --- a/simple-local-avatars.php +++ b/simple-local-avatars.php @@ -1,11 +1,11 @@ Date: Tue, 23 Oct 2018 08:37:21 -0600 Subject: [PATCH 22/22] Give upgrade notice the same text as the changelog --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 029ad175..7b8653c3 100644 --- a/readme.txt +++ b/readme.txt @@ -110,7 +110,7 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei == Upgrade Notice == = 2.1 = -*Important note:* All newly uploaded local avatars will appear in the media library, even when uploaded by contributors or subscribers. However, this does not give them access to the media library. +*Important note:* All avatar uploads now go into the media library. Don't worry - users without the ability to upload files cannot otherwise see the contents of your media library. This allows local avatars to respect other functionality your site may have around uploaded images, such as external hosting. = 2.0 = Upgraded to take advantage of *WordPress 3.5 and newer*. Does not support older versions! This has also *not* been tested with front end profile plug-ins - feedback welcome. Note that several language strings have been added or modified - revised translations would be welcome!