Plugin Directory

Changeset 1971315


Ignore:
Timestamp:
11/09/2018 05:25:29 AM (7 years ago)
Author:
rinatkhaziev
Message:

Merge 1.3.2 from GitHub

Location:
frontend-uploader/trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • frontend-uploader/trunk/frontend-uploader.php

    r1734078 r1971315  
    44Description: Allow your visitors to upload content and moderate it.
    55Author: Rinat Khaziev, Daniel Bachhuber
    6 Version: 1.3.1
     6Version: 1.3.2
    77Author URI: http://digitallyconscious.com
    88
     
    2626
    2727// Define consts and bootstrap and dependencies
    28 define( 'FU_VERSION', '1.3.1' );
     28define( 'FU_VERSION', '1.3.2' );
    2929define( 'FU_ROOT' , dirname( __FILE__ ) );
    3030define( 'FU_FILE_PATH' , FU_ROOT . '/' . basename( __FILE__ ) );
     
    156156        foreach ( $fu_mime_types as $extension => $details ) {
    157157            // Skip if it's not in the settings
    158             if ( !in_array( $extension, $enabled ) )
     158            if ( ! in_array( $extension, $enabled, true ) )
    159159                continue;
    160160
     
    199199        global $wp_version;
    200200        if ( version_compare( $wp_version, '3.3', '<' ) ) {
    201             wp_die( __( 'Frontend Uploader requires WordPress 3.3 or newer. Please upgrade.', 'frontend-uploader' ) );
     201            wp_die( esc_html__( 'Frontend Uploader requires WordPress 3.3 or newer. Please upgrade.', 'frontend-uploader' ) );
    202202        }
    203203
     
    230230
    231231        $screen = get_current_screen();
    232         if ( ! defined( 'DOING_AJAX' ) && $screen && isset( $screen->base ) && $screen->base == 'upload' && ( !isset( $_GET['page'] ) || $_GET['page'] != 'manage_frontend_uploader' ) ) {
     232        if ( ! defined( 'DOING_AJAX' ) && $screen && isset( $screen->base ) && $screen->base === 'upload' && ( !isset( $_GET['page'] ) || $_GET['page'] !== 'manage_frontend_uploader' ) ) {
    233233            $where = str_replace( "post_status = 'private'", "post_status = 'inherit'", $where );
    234234        }
     
    242242     */
    243243    function _is_public() {
    244         return ( current_user_can( 'read' ) && 'on' == $this->settings['auto_approve_user_files'] ) || ( 'on' == $this->settings['auto_approve_any_files'] );
     244        return ( current_user_can( 'read' ) && 'on' === $this->settings['auto_approve_user_files'] ) || ( 'on' === $this->settings['auto_approve_any_files'] );
    245245    }
    246246
     
    290290            $typecheck = wp_check_filetype_and_ext( $k['tmp_name'], $k['name'], false );
    291291            // Add an error message if MIME-type is not allowed
    292             if ( ! in_array( $typecheck['type'], (array) $this->allowed_mime_types ) ) {
     292            if ( ! in_array( $typecheck['type'], (array) $this->allowed_mime_types, true ) ) {
    293293                $errors['fu-disallowed-mime-type'][] = array( 'name' => $k['name'], 'mime' => $k['type'] );
    294294                continue;
     
    323323
    324324            // Obfuscate filename if setting is present
    325             if (  isset( $this->settings['obfuscate_file_name'] ) && 'on' == $this->settings['obfuscate_file_name']  ){
     325            if ( isset( $this->settings['obfuscate_file_name'] ) && 'on' === $this->settings['obfuscate_file_name']  ){
    326326                $fn = explode( '.', $k['name'] );
    327                 $m['name'] = uniqid( mt_rand( 1, 1000 ) , true ) . '.' . end( $fn );
     327                $m['name'] = uniqid( wp_rand( 1, 1000 ) , true ) . '.' . end( $fn );
    328328            }
    329329
     
    390390     */
    391391    function wp_kses_add_srcset( $tags, $context ) {
    392         if ( $context == 'post' )
     392        if ( $context === 'post' )
    393393            $tags['img']['srcset'] = true;
    394394
     
    524524        $this->form_fields = !empty( $this->form_fields ) ? $this->form_fields : $this->_get_fields_for_form( $form_post_id, $hash );
    525525
    526         $layout = isset( $_POST['form_layout'] ) && !empty( $_POST['form_layout'] ) ? $_POST['form_layout'] : 'image';
     526        $layout = isset( $_POST['form_layout'] ) && ! empty( $_POST['form_layout'] ) ? sanitize_text_field( $_POST['form_layout'] ) : 'image';
    527527
    528528        /**
     
    586586    function _notify_admin( $result = array() ) {
    587587        // Email notifications are disabled, or upload has failed, bailing
    588         if ( ! ( 'on' == $this->settings['notify_admin'] && $result['success'] ) )
     588        if ( ! ( 'on' === $this->settings['notify_admin'] && $result['success'] ) )
    589589            return;
    590590
     
    627627        if ( empty( $result ) || !is_array( $result ) ) {
    628628            wp_safe_redirect( wp_get_referer() );
     629            exit;
     630
    629631            return;
    630632        }
     
    632634        // Either redirect to success page if it's set and valid
    633635        // Or to referrer
    634         $url = isset( $_POST['success_page'] ) && filter_var( $_POST['success_page'], FILTER_VALIDATE_URL ) ? $_POST['success_page'] : wp_get_referer();
     636        $url = isset( $_POST['success_page'] ) && filter_var( $_POST['success_page'], FILTER_VALIDATE_URL ) ? esc_url_raw( $_POST['success_page'] ) : wp_get_referer();
    635637
    636638        // $query_args will hold everything that's needed for displaying notices to user
     
    688690            include_once FU_ROOT . '/' . $file;
    689691        } else {
    690             wp_die( __( "Couldn't find template file", 'frontend-uploader' ) );
     692            wp_die( esc_html__( "Couldn't find template file", 'frontend-uploader' ) );
    691693        }
    692694    }
     
    697699     */
    698700    private function _set_global_query_for_tables( $type = 'posts' ) {
    699         if ( ! in_array( $type, array( 'posts', 'media' ) ) )
     701        if ( ! in_array( $type, array( 'posts', 'media' ), true ) )
    700702            return false;
    701703
     
    752754        add_media_page( __( 'Manage UGC', 'frontend-uploader' ), __( 'Manage UGC', 'frontend-uploader' ), $this->manage_permissions, 'manage_frontend_uploader', array( $this, 'admin_list' ) );
    753755        foreach ( (array) $this->settings['enabled_post_types'] as $cpt ) {
    754             if ( $cpt == 'post' ) {
     756            if ( $cpt === 'post' ) {
    755757                add_posts_page( __( 'Manage UGC Posts', 'frontend-uploader' ), __( 'Manage UGC', 'frontend-uploader' ), $this->manage_permissions, 'manage_frontend_uploader_posts', array( $this, 'admin_posts_list' ) );
    756758                continue;
     
    773775        }
    774776
    775         $post = get_post( $_GET['id'] );
    776 
    777         if ( is_object( $post ) && $post->post_status == 'private' ) {
     777        $post = get_post( (int) $_GET['id'] );
     778
     779        if ( is_object( $post ) && $post->post_status === 'private' ) {
    778780            $post->post_status = 'inherit';
    779781            wp_update_post( $post );
     
    803805        }
    804806
    805         $post = get_post( $_GET['id'] );
     807        $post = get_post( (int) $_GET['id'] );
    806808
    807809        if ( is_object( $post ) ) {
     
    822824                'page' => "manage_frontend_uploader_{$post->post_type}s",
    823825                'approved' => 1,
    824                 'post_type' => $post->post_type != 'post' ? $post->post_type : '',
     826                'post_type' => $post->post_type !== 'post' ? $post->post_type : '',
    825827            );
    826828
     
    884886        extract( $atts );
    885887
    886         $role = in_array( $role, array( 'meta', 'title', 'description', 'author', 'internal', 'content' ) ) ? $role : 'meta';
     888        $role = in_array( $role, array( 'meta', 'title', 'description', 'author', 'internal', 'content' ), true ) ? $role : 'meta';
    887889        $name = sanitize_text_field( $name );
    888890        // Add the field to fields map
     
    910912        // Allow multiple file upload by default.
    911913        // To do so, we need to add array notation to name field: []
    912         if ( !strpos( $name, '[]' ) && $type == 'file' )
     914        if ( !strpos( $name, '[]' ) && $type === 'file' )
    913915            $name = 'files' . '[]';
    914916
     
    916918
    917919        // No need for wrappers or labels for hidden input
    918         if ( $type == 'hidden' )
     920        if ( $type === 'hidden' )
    919921            return $input;
    920922
     
    940942
    941943        // Render WYSIWYG textarea
    942         if ( ( isset( $this->settings['wysiwyg_enabled'] ) && 'on' == $this->settings['wysiwyg_enabled'] ) || $wysiwyg_enabled == true ) {
     944        if ( ( isset( $this->settings['wysiwyg_enabled'] ) && 'on' === $this->settings['wysiwyg_enabled'] ) || $wysiwyg_enabled === true ) {
    943945            ob_start();
    944946            wp_editor( '', $id, array(
     
    10851087        $post_id = (int) $post_id;
    10861088
    1087         $this->enqueue_scripts();
     1089        add_action( 'wp_footer', array( $this, 'enqueue_scripts' ), 0 );
    10881090
    10891091        $form_layout = in_array( $form_layout, array( 'post', 'image', 'media', 'post_image', 'post_media' ), true ) ? $form_layout : 'media';
     
    10911093        ob_start();
    10921094?>
    1093     <form action="<?php echo admin_url( 'admin-ajax.php' ) ?>" method="post" id="ugc-media-form-<?php echo $inst++; ?>" class="<?php echo esc_attr( $class )?> fu-upload-form" enctype="multipart/form-data">
     1095    <form action="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ) ?>" method="post" id="ugc-media-form-<?php echo esc_attr( $inst++ ); ?>" class="<?php echo esc_attr( $class )?> fu-upload-form" enctype="multipart/form-data">
    10941096     <div class="ugc-inner-wrapper">
    10951097         <h2><?php echo esc_html( $title ) ?></h2>
     
    11041106        // Set post type for layouts that include uploading of posts
    11051107        // Put it in front of the main form to allow to override it
    1106         if ( in_array( $form_layout, array( "post_media", "post_image", "post" ) ) ) {
     1108        if ( in_array( $form_layout, array( "post_media", "post_image", "post" ), true ) ) {
    11071109            echo $this->shortcode_content_parser( array(
    11081110                    'type' => 'hidden',
     
    11291131        }
    11301132
    1131         if ( !( isset( $this->settings['suppress_default_fields'] ) && 'on' == $this->settings['suppress_default_fields'] ) && ( $suppress_default_fields === false ) ) {
     1133        if ( !( isset( $this->settings['suppress_default_fields'] ) && 'on' === $this->settings['suppress_default_fields'] ) && ( $suppress_default_fields === false ) ) {
    11321134
    11331135            // Display title field
     
    11791181            echo do_shortcode( $content );
    11801182
    1181         if ( !( isset( $this->settings['suppress_default_fields'] ) && 'on' == $this->settings['suppress_default_fields'] ) && ( $suppress_default_fields === false ) ) {
    1182 
    1183             if ( in_array( $form_layout, array( 'image', 'media', 'post_image', 'post_media' ) ) ) {
     1183        if ( !( isset( $this->settings['suppress_default_fields'] ) && 'on' === $this->settings['suppress_default_fields'] ) && ( $suppress_default_fields === false ) ) {
     1184
     1185            if ( in_array( $form_layout, array( 'image', 'media', 'post_image', 'post_media' ), true ) ) {
    11841186                // Default upload field
    11851187                echo $this->shortcode_content_parser( array(
     
    11941196            }
    11951197
    1196             if ( $this->settings['enable_recaptcha_protection' ] == 'on' )
     1198            if ( $this->settings['enable_recaptcha_protection' ] === 'on' )
    11971199                echo fu_get_recaptcha_markup();
    11981200
     
    12361238            ), null, 'input' );
    12371239
    1238         if ( in_array( $form_layout, array( 'post_media', 'post_image' ) ) ) {
     1240        if ( in_array( $form_layout, array( 'post_media', 'post_image' ), true ) ) {
    12391241                    // One of supported form layouts
    12401242            echo $this->shortcode_content_parser( array(
     
    14541456         * Otherwise it produces JS errors, potentially breaking some post edit screen features
    14551457         */
    1456         if ( $screen && 'media_page_manage_frontend_uploader' == $screen->base )
     1458        if ( $screen && 'media_page_manage_frontend_uploader' === $screen->base )
    14571459            wp_enqueue_script( 'media', array( 'jquery' ) );
    14581460    }
     
    15161518    function _enable_akismet_protection() {
    15171519        // Maybe include Akismet
    1518         if ( isset( $this->settings['enable_akismet_protection'] ) && 'on' == $this->settings['enable_akismet_protection'] ) {
     1520        if ( isset( $this->settings['enable_akismet_protection'] ) && 'on' === $this->settings['enable_akismet_protection'] ) {
    15191521            require_once FU_ROOT . '/lib/php/akismet.php';
    15201522        }
  • frontend-uploader/trunk/lib/js/frontend-uploader.js

    r1402587 r1971315  
    1 jQuery( function($) {
    2     // Drop in _.string
    3     _.mixin(s.exports());
    4     var uploadForm = $( '.fu-upload-form' );
    5     var uploadFormInputs = uploadForm.find('input[type="text"], textarea');
     1jQuery(function ($) {
     2  // Drop in _.string
     3  _.mixin(s.exports());
     4  var uploadForm = $('.fu-upload-form');
     5  var uploadFormInputs = uploadForm.find('input[type="text"], textarea');
     6  _.each( uploadForm, function (f, i) {
     7    $(f).validate({
     8      submitHandler: function (form) {
     9        form.submit();
     10      }
     11    })
     12  });
    613
    7     uploadForm.validate({
    8         submitHandler: function(form) {
    9         form.submit();
    10         }
    11     });
     14  /**
     15   * Only set the fields if an error happened
     16   * @return {[type]} [description]
     17   */
     18  var shouldPopulate = function () {
     19    var qv = getQueryVariable('response');
     20    return false === (qv == '' || qv == 'fu-sent' || qv == 'fu-post-sent');
     21  };
    1222
    13     /**
    14      * Only set the fields if an error happened
    15      * @return {[type]} [description]
    16      */
    17     var shouldPopulate = function() {
    18         var qv = getQueryVariable('response');
    19         return false === ( qv == '' || qv == 'fu-sent' || qv == 'fu-post-sent' );
    20     };
     23  /**
     24   * Extract needed var from location.search
     25   * @param  {[type]} variable [description]
     26   * @return {[type]}          [description]
     27   */
     28  var getQueryVariable = function (variable) {
     29    var query = window.location.search.substring(1);
     30    var vars = query.split('&');
     31    for (var i = 0; i < vars.length; i++) {
     32      var pair = vars[i].split('=');
     33      if (decodeURIComponent(pair[0]) == variable) {
     34        return decodeURIComponent(pair[1]);
     35      }
     36    }
    2137
    22     /**
    23      * Extract needed var from location.search
    24      * @param  {[type]} variable [description]
    25      * @return {[type]}          [description]
    26      */
    27     var getQueryVariable = function (variable) {
    28         var query = window.location.search.substring(1);
    29         var vars = query.split('&');
    30         for (var i = 0; i < vars.length; i++) {
    31             var pair = vars[i].split('=');
    32             if (decodeURIComponent(pair[0]) == variable) {
    33                 return decodeURIComponent(pair[1]);
    34             }
    35         }
     38    return '';
     39  }
    3640
    37         return '';
    38     }
     41  // Strip all tags and escape HTML
     42  var sanitize = function (str) {
     43    return _.escapeHTML(_.stripTags(str));
     44  };
    3945
    40     // Strip all tags and escape HTML
    41     var sanitize = function( str ) {
    42         return _.escapeHTML( _.stripTags( str ) );
    43     };
     46  /**
     47   * Iterate over form text inputs and textareas and either populate value or remove it from local storage
     48   * @param  {[type]} value [description]
     49   * @param  {[type]} key   [description]
     50   * @param  {[type]} list
     51   * @return {[type]}       [description]
     52   */
     53  _.each(uploadFormInputs, function (value, key, list) {
     54    var lsKey = $(value).prop('id') + ':value';
     55    if (shouldPopulate()) {
     56      $(value).val(sanitize(localStorage.getItem(lsKey)));
     57    } else {
     58      localStorage.removeItem(lsKey);
     59    }
     60  });
    4461
    45     /**
    46      * Iterate over form text inputs and textareas and either populate value or remove it from local storage
    47      * @param  {[type]} value [description]
    48      * @param  {[type]} key   [description]
    49      * @param  {[type]} list  )             {       var lsKey [description]
    50      * @return {[type]}       [description]
    51      */
    52     _.each( uploadFormInputs, function( value, key, list ) {
    53         var lsKey = $(value).prop('id') + ':value';
    54         if ( shouldPopulate() ) {
    55             $(value).val( sanitize( localStorage.getItem( lsKey ) ) );
    56         } else {
    57             localStorage.removeItem( lsKey );
    58         }
    59     });
     62  /**
     63   * Store input value in localStorage
     64   */
     65  uploadFormInputs.on('change keyup focusin focusout', function (e) {
     66    var el = $(e.target);
    6067
    61     /**
    62      * Store input value in localStorage
    63      */
    64     uploadFormInputs.on( "change keyup focusin focusout", function( e ) {
    65         var el = $(e.target);
     68    var key = el.prop('id') + ':value';
    6669
    67         var key = el.prop('id') + ':value';
     70    // you can never be too safe
     71    var val = sanitize(el.val());
    6872
    69         // you can never be too safe
    70         var val = sanitize( el.val() );
    71 
    72         localStorage.setItem( key, val );
    73     });
     73    localStorage.setItem(key, val);
     74  });
    7475
    7576});
  • frontend-uploader/trunk/lib/php/akismet.php

    r1012202 r1971315  
    1818
    1919    $content['comment_author'] = isset( $_POST['post_author'] ) ? sanitize_text_field( $_POST['post_author'] ) : null;
    20     $content['comment_content'] = isset( $_POST[ 'post_content' ] ) ? $_POST['post_content'] : null;
     20    $content['comment_content'] = isset( $_POST[ 'post_content' ] ) ? wp_kses_post( $_POST['post_content'] ) : null;
    2121
    2222    // Permalink of the post with upload form, fallback to wp_get_referer()
    2323    // Fallback is used to
    24     $content['permalink'] = isset( $_POST['form_post_id'] ) ? get_permalink( $_POST['form_post_id'] ) : wp_get_referer();
     24    $content['permalink'] = isset( $_POST['form_post_id'] ) ? get_permalink( sanitize_text_area( $_POST['form_post_id'] ) ) : wp_get_referer();
    2525
    2626    // Set required Akismet values
    27     $content['user_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
    28     $content['user_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
    29     $content['referrer'] = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : null;
     27    $content['user_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : null;
     28    $content['user_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : null;
     29    $content['referrer'] = isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : null;
    3030    $content['blog'] = get_option( 'home' );
    3131    $content['blog_lang']    = get_locale();
     
    3636    $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW', 'ff', 'fu_nonce' );
    3737    foreach ( $_POST as $key => $value ) {
    38         if ( !in_array( $key, $ignore ) && is_string( $value ) )
     38        if ( ! in_array( $key, $ignore, true ) && is_string( $value ) )
    3939            $content["POST_{$key}"] = $value;
    4040    }
    4141
    4242    foreach ( $_SERVER as $key => $value ) {
    43         if ( !in_array( $key, $ignore ) && is_string( $value ) )
     43        if ( ! in_array( $key, $ignore, true ) && is_string( $value ) )
    4444            $content["$key"] = $value;
    4545        else
     
    5252
    5353    // It's a spam
    54     if ( $response[1] == 'true' )
     54    if ( $response[1] === 'true' )
    5555        $should_process = false;
    5656
  • frontend-uploader/trunk/lib/php/class-frontend-uploader-wp-posts-list-table.php

    r1699139 r1971315  
    1010
    1111        $screen = get_current_screen();
    12         if ( $screen->post_type == '' ) {
     12        if ( $screen->post_type === '' ) {
    1313            $screen->post_type ='post';
    1414        }
     
    2121    function _add_row_actions( $actions, $post ) {
    2222        unset( $actions['inline hide-if-no-js'] );
    23         if ( $post->post_status == 'private' ) {
     23        if ( $post->post_status === 'private' ) {
    2424            $actions['pass'] = '<a href="'.admin_url( 'admin-ajax.php' ).'?action=approve_ugc_post&id=' . $post->ID . '&post_type=' . $post->post_type . '">'. __( 'Approve', 'frontend-uploader' ) .'</a>';
    2525            $actions['delete'] = '<a onclick="return showNotice.warn();" href="'.admin_url( 'admin-ajax.php' ).'?action=delete_ugc&id=' . $post->ID . '&post_type=' . $post->post_type . '&fu_nonce=' . wp_create_nonce( FU_NONCE ). '">'. __( 'Delete Permanently', 'frontend-uploader' ) .'</a>';
  • frontend-uploader/trunk/lib/php/class-html-helper.php

    r1728963 r1971315  
    2020     */
    2121    function checkboxes( $name = '', $description = '', $data = array(), $checked = array() ) {
    22         if ( $name != '' ) {
     22        if ( $name !== '' ) {
    2323            $name = filter_var( $name, FILTER_SANITIZE_STRING );
    2424            if ( $description );
     
    2626            echo '<input type="hidden" name="' . esc_attr( $name ) .'" value="" />';
    2727            foreach ( (array) $data as $item ) {
    28                 $is_checked_attr =  in_array( $item, (array) $checked ) ? ' checked="true" ' : '';
     28                $is_checked_attr =  in_array( $item, (array) $checked, true ) ? ' checked="true" ' : '';
    2929                $item = filter_var( $item, FILTER_SANITIZE_STRING );
    3030                echo '<div class="sm-input-wrapper">';
    31                 echo '<input type="checkbox" name="' . esc_attr( $name ) . '[]" value="' . esc_attr( $item ) . '" id="' .esc_attr( $name ) . esc_attr( $item )  . '" ' . $is_checked_attr . ' />';
     31                echo '<input type="checkbox" name="' . esc_attr( $name ) . '[]" value="' . esc_attr( $item ) . '" id="' .esc_attr( $name ) . esc_attr( $item )  . '" ' . esc_attr( $is_checked_attr ) . ' />';
    3232                echo '<label for="' .esc_attr( $name ) . esc_attr( $item )  . '">' . esc_attr ( $item ) . '</label>';
    3333                echo '</div>';
     
    7777        case 'file':
    7878        case 'checkbox':
     79        case 'email':
     80        case 'date':
     81        case 'datetime':
     82        case 'datetime-local':
     83        case 'color':
     84        case 'month':
     85        case 'number':
     86        case 'password':
     87        case 'range':
     88        case 'search':
     89        case 'reset':
     90        case 'button':
     91        case 'tel':
     92        case 'time':
     93        case 'url':
     94        case 'week':
    7995            return $this->_text( $name, $type,  $data, $attrs ) ;
    8096            break;
     
    106122        foreach ( (array) $data as $key => $value ) {
    107123            $attrs_to_pass = array( 'value' => $key );
    108             if ( isset( $attrs[ 'default' ] ) && $key == $attrs[ 'default' ] )
     124            if ( isset( $attrs[ 'default' ] ) && $key === $attrs[ 'default' ] )
    109125                $attrs_to_pass[ 'selected' ] = 'selected';
    110126            $ret .= $this->element( 'option', $value, $attrs_to_pass, false );
     
    146162        $allowed = apply_filters( 'hh_allowed_html_elements' , array( 'div', 'p', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'option', 'label', 'textarea', 'select', 'option', 'fieldset' ) );
    147163        $attr_string = $this->_format_attributes( $params );
    148         if ( in_array( $tag, $allowed ) )
     164        if ( in_array( $tag, $allowed, true ) )
    149165            return "<{$tag} {$attr_string}>" . ( $escape ? esc_html ( $content ) : $content ) . "</{$tag}>";
    150166    }
     
    165181
    166182        foreach ( (array) $attrs as $attr => $value ) {
    167             if ( in_array( $attr, $this->_allowed_html_attrs() ) && $value != '' )
     183            if ( in_array( $attr, $this->_allowed_html_attrs(), true ) && $value !== '' )
    168184                $attr_string .= " {$attr}='" . esc_attr ( $value ) . "'";
    169185        }
     
    182198        $attr_string = $this->_format_attributes( $params );
    183199        if ( filter_var( trim( $url ), FILTER_VALIDATE_URL ) )
    184             return '<a href="' . esc_url( trim( $url ) ) . '" ' . $attr_string . '>' . ( $title != '' ? esc_html ( $title ) : esc_url( trim( $url ) ) ) . '</a>';
     200            return '<a href="' . esc_url( trim( $url ) ) . '" ' . $attr_string . '>' . ( $title !== '' ? esc_html ( $title ) : esc_url( trim( $url ) ) ) . '</a>';
    185201    }
    186202
     
    211227            'max',
    212228            'placeholder',
    213 
    214229        ) );
    215230    }
  • frontend-uploader/trunk/lib/php/frontend-uploader-settings.php

    r1688580 r1971315  
    2020    function action_current_screen() {
    2121        $screen = get_current_screen();
    22         if ( in_array( $screen->base, array( 'settings_page_fu_settings', 'options' ) ) ) {
     22        if ( in_array( $screen->base, array( 'settings_page_fu_settings', 'options' ), true ) ) {
    2323            $this->settings_api->set_sections( $this->get_settings_sections() );
    2424            $this->settings_api->set_fields( $this->get_settings_fields() );
     
    3535        $fu_public_post_types = get_post_types( array( 'public' => true ), 'objects' );
    3636        foreach( $fu_public_post_types as $slug => $post_object ) {
    37             if ( $slug == 'attachment' ) {
     37            if ( $slug === 'attachment' ) {
    3838                unset( $fu_public_post_types[$slug] );
    3939                continue;
  • frontend-uploader/trunk/lib/php/recaptcha.php

    r1688580 r1971315  
    2121            'secret' => fu_get_option( 'recaptcha_secret_key' ),
    2222            'response' => sanitize_text_field( $_POST['g-recaptcha-response'] ),
    23             'remoteip' => $_SERVER['REMOTE_ADDR']
     23            'remoteip' => sanitize_text_field( $_SERVER['REMOTE_ADDR'] )
    2424        ),
    2525        'timeout' => 3,
  • frontend-uploader/trunk/lib/php/settings-api/class.settings-api.php

    r1030331 r1971315  
    103103        //register settings sections
    104104        foreach ( $this->settings_sections as $section ) {
    105             if ( false == get_option( $section['id'] ) ) {
     105            if ( false === get_option( $section['id'] ) ) {
    106106                add_option( $section['id'] );
    107107            }
     
    143143    function callback_text( $args ) {
    144144
    145         $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
     145        $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
    146146        $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
    147147
    148         $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
    149         $html .= sprintf( '<span class="description"> %s</span>', $args['desc'] );
     148        $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $value ) );
     149        $html .= sprintf( '<span class="description"> %s</span>', esc_html( $args['desc'] ) );
    150150
    151151        echo $html;
     
    159159    function callback_checkbox( $args ) {
    160160
    161         $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
    162 
    163         $html = sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" />', $args['section'], $args['id'] );
    164         $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s />', $args['section'], $args['id'], $value, checked( $value, 'on', false ) );
    165         $html .= sprintf( '<label for="%1$s[%2$s]"> %3$s</label>', $args['section'], $args['id'], $args['desc'] );
     161        $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
     162
     163        $html = sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" />', esc_attr( $args['section'] ), esc_attr( $args['id'] ) );
     164        $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s />', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $value ), checked( $value, 'on', false ) );
     165        $html .= sprintf( '<label for="%1$s[%2$s]"> %3$s</label>', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_html( $args['desc'] ) );
    166166
    167167        echo $html;
     
    180180        foreach ( $args['options'] as $key => $label ) {
    181181            $checked = isset( $value[$key] ) ? $value[$key] : '0';
    182             $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s"%4$s />', $args['section'], $args['id'], $key, checked( $checked, $key, false ) );
    183             $html .= sprintf( '<label for="%1$s[%2$s][%4$s]"> %3$s</label><br>', $args['section'], $args['id'], $label, $key );
    184         }
    185         $html .= sprintf( '<span class="description"> %s</label>', $args['desc'] );
     182            $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s"%4$s />', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $key ), checked( $checked, $key, false ) );
     183            $html .= sprintf( '<label for="%1$s[%2$s][%4$s]"> %3$s</label><br>', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_html( $label ), esc_attr( $key ) );
     184        }
     185        $html .= sprintf( '<span class="description"> %s</label>', esc_html( $args['desc'] ) );
    186186
    187187        echo $html;
     
    199199        $html = '';
    200200        foreach ( $args['options'] as $key => $label ) {
    201             $html .= sprintf( '<input type="radio" class="radio" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s"%4$s />', $args['section'], $args['id'], $key, checked( $value, $key, false ) );
    202             $html .= sprintf( '<label for="%1$s[%2$s][%4$s]"> %3$s</label><br>', $args['section'], $args['id'], $label, $key );
    203         }
    204         $html .= sprintf( '<span class="description"> %s</label>', $args['desc'] );
     201            $html .= sprintf( '<input type="radio" class="radio" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s"%4$s />', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $key ), checked( $value, $key, false ) );
     202            $html .= sprintf( '<label for="%1$s[%2$s][%4$s]"> %3$s</label><br>', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_html( $label ), esc_attr( $key ) );
     203        }
     204        $html .= sprintf( '<span class="description"> %s</label>', esc_html( $args['desc'] ) );
    205205
    206206        echo $html;
     
    214214    function callback_select( $args ) {
    215215
    216         $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
     216        $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
    217217        $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
    218218
    219         $html = sprintf( '<select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
     219        $html = sprintf( '<select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]">', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ) );
    220220        foreach ( $args['options'] as $key => $label ) {
    221             $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $value, $key, false ), $label );
     221            $html .= sprintf( '<option value="%s"%s>%s</option>', esc_attr( $key ), selected( $value, $key, false ), esc_html( $label ) );
    222222        }
    223223        $html .= sprintf( '</select>' );
    224         $html .= sprintf( '<span class="description"> %s</span>', $args['desc'] );
     224        $html .= sprintf( '<span class="description"> %s</span>', esc_html( $args['desc'] ) );
    225225
    226226        echo $html;
     
    234234    function callback_textarea( $args ) {
    235235
    236         $value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
     236        $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
    237237        $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
    238238
    239         $html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]">%4$s</textarea>', $size, $args['section'], $args['id'], $value );
    240         $html .= sprintf( '<br><span class="description"> %s</span>', $args['desc'] );
     239        $html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]">%4$s</textarea>', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_textarea( $value ) );
     240        $html .= sprintf( '<br><span class="description"> %s</span>', esc_html( $args['desc'] ) );
    241241
    242242        echo $html;
     
    249249     */
    250250    function callback_html( $args ) {
    251         echo $args['desc'];
     251        echo esc_textarea( $args['desc'] );
    252252    }
    253253
     
    262262        $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : '500px';
    263263
    264         echo '<div style="width: ' . $size . ';">';
     264        echo '<div style="width: ' . esc_attr( $size ) . ';">';
    265265
    266266        wp_editor( $value, $args['section'] . '[' . $args['id'] . ']', array( 'teeny' => true, 'textarea_rows' => 10 ) );
     
    268268        echo '</div>';
    269269
    270         echo sprintf( '<br><span class="description"> %s</span>', $args['desc'] );
     270        echo sprintf( '<br><span class="description"> %s</span>', esc_html( $args['desc'] ) );
    271271    }
    272272
     
    282282        $id = $args['section']  . '[' . $args['id'] . ']';
    283283        $js_id = $args['section']  . '\\\\[' . $args['id'] . '\\\\]';
    284         $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
    285         $html .= '<input type="button" class="button wpsf-browse" id="'. $id .'_button" value="Browse" />
     284        $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $value ) );
     285        $html .= '<input type="button" class="button wpsf-browse" id="'. esc_attr( $id ) .'_button" value="Browse" />
    286286        <script type="text/javascript">
    287287        jQuery(document).ready(function($){
    288             $("#'. $js_id .'_button").click(function() {
     288            $("#'. wp_json_encode( $js_id ) .'_button").click(function() {
    289289                tb_show("", "media-upload.php?post_id=0&amp;type=image&amp;TB_iframe=true");
    290290                window.original_send_to_editor = window.send_to_editor;
     
    294294                    url = $(html).attr(\'src\');
    295295                };
    296                 $("#'. $js_id .'").val(url);
     296                $("#'. wp_json_encode( $js_id ) .'").val(url);
    297297                tb_remove();
    298298                window.send_to_editor = window.original_send_to_editor;
     
    302302        });
    303303        </script>';
    304         $html .= sprintf( '<span class="description"> %s</span>', $args['desc'] );
     304        $html .= sprintf( '<span class="description"> %s</span>', esc_html( $args['desc'] ) );
    305305
    306306        echo $html;
     
    317317        $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
    318318
    319         $html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
    320         $html .= sprintf( '<span class="description"> %s</span>', $args['desc'] );
     319        $html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $value ) );
     320        $html .= sprintf( '<span class="description"> %s</span>', esc_html( $args['desc'] ) );
    321321
    322322        echo $html;
     
    358358        foreach( $this->settings_fields as $section => $options ) {
    359359            foreach ( $options as $option ) {
    360                 if ( $option['name'] != $slug )
     360                if ( $option['name'] !== $slug )
    361361                    continue;
    362362                // Return the callback name
     
    395395
    396396        foreach ( $this->settings_sections as $tab ) {
    397             $html .= sprintf( '<a href="#%1$s" class="nav-tab" id="%1$s-tab">%2$s</a>', $tab['id'], $tab['title'] );
     397            $html .= sprintf( '<a href="#%1$s" class="nav-tab" id="%1$s-tab">%2$s</a>', esc_attr( esc_url( $tab['id'] ) ), esc_html( $tab['title'] ) );
    398398        }
    399399
     
    413413            <div class="postbox">
    414414                <?php foreach ( $this->settings_sections as $form ) { ?>
    415                     <div id="<?php echo $form['id']; ?>" class="group inside">
     415                    <div id="<?php echo esc_attr( $form['id'] ); ?>" class="group inside">
    416416                        <form method="post" action="options.php">
    417417
  • frontend-uploader/trunk/lib/views/manage-ugc-media.tpl.php

    r1402587 r1971315  
    33set_current_screen( 'upload' );
    44if ( ! current_user_can( 'upload_files' ) )
    5     wp_die( __( 'You do not have permission to upload files.', 'frontend-uploader' ) );
     5    wp_die( esc_html__( 'You do not have permission to upload files.', 'frontend-uploader' ) );
    66
    77$wp_list_table = new FU_WP_Media_List_Table();
     
    1212?>
    1313<div class="wrap">
    14 <?php screen_icon(); ?>
    1514<h2><?php echo esc_html( $title ); ?> <?php
    1615if ( isset( $_REQUEST['s'] ) && $_REQUEST['s'] )
    17     printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'frontend-uploader' ) . '</span>', get_search_query() ); ?>
     16    printf( '<span class="subtitle">' . esc_html__( 'Search results for &#8220;%s&#8221;', 'frontend-uploader' ) . '</span>', get_search_query() ); ?>
    1817</h2>
    1918
     
    3837if ( isset( $_GET['trashed'] ) && (int) $_GET['trashed'] ) {
    3938    $message = sprintf( _n( 'Media attachment moved to the trash.', '%d media attachments moved to the trash.', $_GET['trashed'] ), number_format_i18n( $_GET['trashed'] ) );
    40     $message .= ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? $_GET['ids'] : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
     39    $message .= ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? sanitize_text_field( $_GET['ids'] ) : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
    4140    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'trashed' ), $_SERVER['REQUEST_URI'] );
    4241}
    4342
    4443if ( isset( $_GET['untrashed'] ) && (int) $_GET['untrashed'] ) {
    45     $message = sprintf( _n( 'Media attachment restored from the trash.', '%d media attachments restored from the trash.', $_GET['untrashed'] ), number_format_i18n( $_GET['untrashed'] ) );
     44    $message = sprintf( _n( 'Media attachment restored from the trash.', '%d media attachments restored from the trash.', sanitize_text_field( $_GET['untrashed'] ) ), number_format_i18n( $_GET['untrashed'] ) );
    4645    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'untrashed' ), $_SERVER['REQUEST_URI'] );
    4746}
     
    5453$messages[2] = __( 'Media permanently deleted.', 'frontend-uploader' );
    5554$messages[3] = __( 'Error saving media attachment.', 'frontend-uploader' );
    56 $messages[4] = __( 'Media moved to the trash.', 'frontend-uploader' ) . ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? $_GET['ids'] : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
     55$messages[4] = __( 'Media moved to the trash.', 'frontend-uploader' ) . ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? sanitize_text_field( $_GET['ids'] ) : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
    5756$messages[5] = __( 'Media restored from the trash.', 'frontend-uploader' );
    5857
    5958if ( isset( $_GET['message'] ) && (int) $_GET['message'] ) {
    60     $message = $messages[$_GET['message']];
     59    $message = $messages[ sanitize_text_field( $_GET['message'] ) ];
    6160    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'message' ), $_SERVER['REQUEST_URI'] );
    6261}
  • frontend-uploader/trunk/lib/views/manage-ugc-posts.tpl.php

    r1468826 r1971315  
    22$title = __( 'Manage UGC Posts', 'frontend-uploader' );
    33if ( ! current_user_can( 'publish_posts' ) )
    4     wp_die( __( 'You do not have permission to publish posts.', 'frontend-uploader' ) );
     4    wp_die( esc_html__( 'You do not have permission to publish posts.', 'frontend-uploader' ) );
    55
    66$wp_post_list_table = new FU_WP_Posts_List_Table();
     
    1111
    1212<div class="wrap">
    13 <?php screen_icon(); ?>
    1413<h2><?php echo esc_html( $title ); ?><?php
    1514if ( isset( $_REQUEST['s'] ) && $_REQUEST['s'] )
    16     printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'frontend-uploader' ) . '</span>', get_search_query() ); ?>
     15    printf( '<span class="subtitle">' . esc_html__( 'Search results for &#8220;%s&#8221;', 'frontend-uploader' ) . '</span>', get_search_query() ); ?>
    1716</h2>
    1817
     
    3635
    3736if ( isset( $_GET['trashed'] ) && (int) $_GET['trashed'] ) {
    38     $message = sprintf( _n( 'Post moved to the trash.', '%d Posts moved to the trash.', $_GET['trashed'] ), number_format_i18n( $_GET['trashed'] ) );
    39     $message .= ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? $_GET['ids'] : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
     37    $message = sprintf( _n( 'Post moved to the trash.', '%d Posts moved to the trash.', sanitize_text_field( $_GET['trashed'] ) ), number_format_i18n( $_GET['trashed'] ) );
     38    $message .= ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? sanitize_text_field( $_GET['ids'] ) : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
    4039    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'trashed' ), $_SERVER['REQUEST_URI'] );
    4140}
    4241
    4342if ( isset( $_GET['untrashed'] ) && (int) $_GET['untrashed'] ) {
    44     $message = sprintf( _n( 'Post restored from the trash.', '%d Posts restored from the trash.', $_GET['untrashed'] ), number_format_i18n( $_GET['untrashed'] ) );
     43    $message = sprintf( _n( 'Post restored from the trash.', '%d Posts restored from the trash.', sanitize_text_field( $_GET['untrashed'] ) ), number_format_i18n( $_GET['untrashed'] ) );
    4544    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'untrashed' ), $_SERVER['REQUEST_URI'] );
    4645}
     
    5352$messages[2] = __( 'Media permanently deleted.', 'frontend-uploader' );
    5453$messages[3] = __( 'Error saving Post.', 'frontend-uploader' );
    55 $messages[4] = __( 'Media moved to the trash.', 'frontend-uploader' ) . ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? $_GET['ids'] : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
     54$messages[4] = __( 'Media moved to the trash.', 'frontend-uploader' ) . ' <a href="' . esc_url( wp_nonce_url( 'upload.php?doaction=undo&action=untrash&ids='.( isset( $_GET['ids'] ) ? sanitize_text_field( $_GET['ids'] ) : '' ), "bulk-media" ) ) . '">' . __( 'Undo', 'frontend-uploader' ) . '</a>';
    5655$messages[5] = __( 'Media restored from the trash.', 'frontend-uploader' );
    5756
    5857if ( isset( $_GET['message'] ) && (int) $_GET['message'] ) {
    59     $message = $messages[$_GET['message']];
     58    $message = $messages[ sanitize_text_field( $_GET['message'] ) ];
    6059    $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'message' ), $_SERVER['REQUEST_URI'] );
    6160}
    6261
    6362if ( !empty( $message ) ) { ?>
    64 <div id="message" class="updated"><p><?php echo $message; ?></p></div>
     63<div id="message" class="updated"><p><?php echo esc_html( $message ); ?></p></div>
    6564<?php } ?>
    6665
  • frontend-uploader/trunk/readme.txt

    r1734078 r1971315  
    44Tags: frontend, image, images, media, uploader, upload, video, audio, photo, photos, picture, pictures, file, user generated content, ugc, frontend upload
    55Requires at least: 4.1
    6 Tested up to: 4.8.2
    7 Stable tag: 1.3.1
     6Tested up to: 5.0
     7Stable tag: 1.3.2
    88License: GPLv2 or later
    99
     
    341341== Changelog ==
    342342
     343= 1.3.2 (Nov 2, 2018) =
     344* Bugfix: allow multiple forms to be properly validated if they're rendered on the same page.
     345* Feature: add support for all HTML5 input types
     346
    343347= 1.3.1 (Sep 21, 2017) =
    344348* Bugfix: fix blank page in Manage UGC on Windows machines
Note: See TracChangeset for help on using the changeset viewer.