Merge pull request #1563 from ultimatemember/fix/textarea_html_on

Fix HTML formatted textarea
This commit is contained in:
Mykyta Synelnikov
2024-10-14 12:56:04 +03:00
committed by GitHub
10 changed files with 80 additions and 35 deletions
-11
View File
@@ -1148,14 +1148,3 @@ small.um-max-filesize span{
float: none;
height: auto;
}
.um-textarea-html-value {
border: none;
width: 100%;
max-width: none;
margin: 0;
padding: 0;
overflow: auto;
max-height: none;
height: auto;
}
+1 -1
View File
File diff suppressed because one or more lines are too long
-12
View File
@@ -96,18 +96,6 @@ UM.frontend = {
UM.frontend.cropper.obj = null; // flush our own object
}
}
},
iframe: {
resize: function(obj) {
let newHeight;
// 150 is default height of the iframe in web-browser
if ( obj.contentWindow.document.documentElement.scrollHeight > 150 && obj.contentWindow.document.documentElement.scrollHeight > obj.contentWindow.document.documentElement.offsetHeight ) {
newHeight = obj.contentWindow.document.documentElement.scrollHeight;
} else {
newHeight = obj.contentWindow.document.documentElement.offsetHeight;
}
obj.style.height = newHeight + 'px';
}
}
}
+1 -1
View File
@@ -1 +1 @@
"object"!=typeof window.UM&&(window.UM={}),"object"!=typeof UM.frontend&&(UM.frontend={}),UM.frontend={cropper:{obj:null,init:function(){var o=jQuery(".um-modal .um-single-image-preview img").first();if(o.length&&""!==o.attr("src")){UM.frontend.cropper.obj&&UM.frontend.cropper.destroy();var t=jQuery(".um-modal .um-single-image-preview"),n=o.parent().data("crop"),r=o.parent().data("min_width"),i=o.parent().data("min_height"),d=o.parent().data("ratio"),a=jQuery(".um-modal").find("#um_upload_single").data("ratio"),a=(a&&(d=a.split(":")[0]),jQuery(window).height()-(jQuery(".um-modal-footer a").height()+20)-50-jQuery(".um-modal-header:visible").height());o.css({height:"auto"}),t.css({height:"auto"}),jQuery(window).height()<=400?(t.css({height:a+"px","max-height":a+"px"}),o.css({height:"auto"})):(o.css({height:"auto","max-height":a+"px"}),t.css({height:o.height(),"max-height":a+"px"}));let e;"square"===n?e={minWidth:r,minHeight:i,dragCrop:!1,aspectRatio:1,zoomable:!1,rotatable:!1,dashed:!1}:"cover"===n?(0<Math.round(r/d)&&(i=Math.round(r/d)),e={minWidth:r,minHeight:i,dragCrop:!1,aspectRatio:d,zoomable:!1,rotatable:!1,dashed:!1}):"user"===n&&(e={minWidth:r,minHeight:i,dragCrop:!0,aspectRatio:"auto",zoomable:!1,rotatable:!1,dashed:!1}),e&&(UM.frontend.cropper.obj=new Cropper(o[0],e))}},destroy:function(){0<jQuery(".cropper-container").length&&UM.frontend.cropper.obj&&(UM.frontend.cropper.obj.destroy(),UM.frontend.cropper.obj=null)}},iframe:{resize:function(e){let o;o=150<e.contentWindow.document.documentElement.scrollHeight&&e.contentWindow.document.documentElement.scrollHeight>e.contentWindow.document.documentElement.offsetHeight?e.contentWindow.document.documentElement.scrollHeight:e.contentWindow.document.documentElement.offsetHeight,e.style.height=o+"px"}}},wp.hooks.addAction("um_remove_modal","um_common_frontend",function(){UM.frontend.cropper.destroy()}),wp.hooks.addAction("um_after_removing_preview","um_common_frontend",function(){UM.frontend.cropper.destroy()}),wp.hooks.addAction("um_window_resize","um_common_frontend",function(){UM.frontend.cropper.destroy()});
"object"!=typeof window.UM&&(window.UM={}),"object"!=typeof UM.frontend&&(UM.frontend={}),UM.frontend={cropper:{obj:null,init:function(){var o=jQuery(".um-modal .um-single-image-preview img").first();if(o.length&&""!==o.attr("src")){UM.frontend.cropper.obj&&UM.frontend.cropper.destroy();var t=jQuery(".um-modal .um-single-image-preview"),r=o.parent().data("crop"),n=o.parent().data("min_width"),i=o.parent().data("min_height"),a=o.parent().data("ratio"),d=jQuery(".um-modal").find("#um_upload_single").data("ratio"),d=(d&&(a=d.split(":")[0]),jQuery(window).height()-(jQuery(".um-modal-footer a").height()+20)-50-jQuery(".um-modal-header:visible").height());o.css({height:"auto"}),t.css({height:"auto"}),jQuery(window).height()<=400?(t.css({height:d+"px","max-height":d+"px"}),o.css({height:"auto"})):(o.css({height:"auto","max-height":d+"px"}),t.css({height:o.height(),"max-height":d+"px"}));let e;"square"===r?e={minWidth:n,minHeight:i,dragCrop:!1,aspectRatio:1,zoomable:!1,rotatable:!1,dashed:!1}:"cover"===r?(0<Math.round(n/a)&&(i=Math.round(n/a)),e={minWidth:n,minHeight:i,dragCrop:!1,aspectRatio:a,zoomable:!1,rotatable:!1,dashed:!1}):"user"===r&&(e={minWidth:n,minHeight:i,dragCrop:!0,aspectRatio:"auto",zoomable:!1,rotatable:!1,dashed:!1}),e&&(UM.frontend.cropper.obj=new Cropper(o[0],e))}},destroy:function(){0<jQuery(".cropper-container").length&&UM.frontend.cropper.obj&&(UM.frontend.cropper.obj.destroy(),UM.frontend.cropper.obj=null)}}},wp.hooks.addAction("um_remove_modal","um_common_frontend",function(){UM.frontend.cropper.destroy()}),wp.hooks.addAction("um_after_removing_preview","um_common_frontend",function(){UM.frontend.cropper.destroy()}),wp.hooks.addAction("um_window_resize","um_common_frontend",function(){UM.frontend.cropper.destroy()});
-8
View File
@@ -139,12 +139,4 @@ jQuery(document).ready(function() {
jQuery( '.um-profile-nav a' ).on( 'touchend', function(e) {
jQuery( e.currentTarget).trigger( "click" );
});
let textarea_iframe = jQuery('iframe.um-textarea-html-value');
textarea_iframe.each(function() {
let obj = jQuery(this);
obj.onload = function() {
UM.frontend.iframe.resize(obj[0]);
};
});
});
+1 -1
View File
@@ -1 +1 @@
jQuery(document).ready(function(){jQuery(".um-profile.um-viewing .um-profile-body .um-row").each(function(){var e=jQuery(this);0==e.find(".um-field").length&&(e.prev(".um-row-heading").remove(),e.remove())}),jQuery(".um-profile.um-viewing .um-profile-body").length&&0==jQuery(".um-profile.um-viewing .um-profile-body").find(".um-field").length&&(jQuery(".um-profile.um-viewing .um-profile-body").find(".um-row-heading,.um-row").remove(),jQuery(".um-profile-note").show()),jQuery(document.body).on("click",".um-profile-save",function(e){return e.preventDefault(),jQuery(this).parents(".um.um-profile.um-editing").find("form").trigger("submit"),!1}),jQuery(document.body).on("click",".um-profile-edit-a",function(e){jQuery(this).addClass("active")}),jQuery(document.body).on("click",".um-cover a.um-cover-add, .um-photo a",function(e){e.preventDefault()}),jQuery(document.body).on("click",".um-photo-modal",function(e){e.preventDefault();e=jQuery(this).attr("data-src");return um_new_modal("um_view_photo","fit",!0,e),!1}),jQuery(document.body).on("click",".um-reset-profile-photo",function(e){return jQuery(".um-profile-photo-img img").attr("src",jQuery(this).attr("data-default_src")),user_id=jQuery(this).attr("data-user_id"),metakey="profile_photo",UM.dropdown.hideAll(),jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_profile_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce}}),jQuery(this).parents("li").hide(),!1}),jQuery(document.body).on("click",".um-reset-cover-photo",function(e){var t=jQuery(this);return jQuery(".um-cover-overlay").hide(),jQuery(".um-cover-e").html('<a href="javascript:void(0);" class="um-cover-add" style="height: 370px;"><span class="um-cover-add-i"><i class="um-icon-plus um-tip-n" title="Upload a cover photo"></i></span></a>'),um_responsive(),user_id=jQuery(this).attr("data-user_id"),metakey="cover_photo",jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_cover_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce},success:function(e){t.hide()}}),UM.dropdown.hideAll(),!1}),jQuery(document.body).on("change keyup","#um-meta-bio",function(){if(void 0!==jQuery(this).val()){var t=jQuery(this).data("character-limit"),r=jQuery(this).data("html");let e=t-jQuery(this).val().length;e=(e=1===parseInt(r)?t-jQuery(this).val().replace(/(<([^>]+)>)/gi,"").length:e)<0?0:e,jQuery("span.um-meta-bio-character span.um-bio-limit").text(e);r=e<5?"red":"";jQuery("span.um-meta-bio-character").css("color",r)}}),jQuery("#um-meta-bio").trigger("change"),jQuery(".um-profile form").each(function(){let t=jQuery(this).data("description_key");jQuery(this).find('textarea[name="'+t+'"]').length&&jQuery(document.body).on("change input",'textarea[name="'+t+'"]',function(e){jQuery(this).parents("form").find('textarea[name="'+t+'"]').each(function(){jQuery(this).val(e.currentTarget.value),jQuery("#um-meta-bio")[0]!==e.currentTarget&&jQuery("#um-meta-bio")[0]===jQuery(this)[0]&&jQuery(this).trigger("change")})})}),jQuery(".um-profile-edit a.um_delete-item").on("click",function(e){if(e.preventDefault(),!confirm(wp.i18n.__("Are you sure that you want to delete this user?","ultimate-member")))return!1}),jQuery(".um-profile-nav a").on("touchend",function(e){jQuery(e.currentTarget).trigger("click")}),jQuery("iframe.um-textarea-html-value").each(function(){let e=jQuery(this);e.onload=function(){UM.frontend.iframe.resize(e[0])}})});
jQuery(document).ready(function(){jQuery(".um-profile.um-viewing .um-profile-body .um-row").each(function(){var e=jQuery(this);0==e.find(".um-field").length&&(e.prev(".um-row-heading").remove(),e.remove())}),jQuery(".um-profile.um-viewing .um-profile-body").length&&0==jQuery(".um-profile.um-viewing .um-profile-body").find(".um-field").length&&(jQuery(".um-profile.um-viewing .um-profile-body").find(".um-row-heading,.um-row").remove(),jQuery(".um-profile-note").show()),jQuery(document.body).on("click",".um-profile-save",function(e){return e.preventDefault(),jQuery(this).parents(".um.um-profile.um-editing").find("form").trigger("submit"),!1}),jQuery(document.body).on("click",".um-profile-edit-a",function(e){jQuery(this).addClass("active")}),jQuery(document.body).on("click",".um-cover a.um-cover-add, .um-photo a",function(e){e.preventDefault()}),jQuery(document.body).on("click",".um-photo-modal",function(e){e.preventDefault();e=jQuery(this).attr("data-src");return um_new_modal("um_view_photo","fit",!0,e),!1}),jQuery(document.body).on("click",".um-reset-profile-photo",function(e){return jQuery(".um-profile-photo-img img").attr("src",jQuery(this).attr("data-default_src")),user_id=jQuery(this).attr("data-user_id"),metakey="profile_photo",UM.dropdown.hideAll(),jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_profile_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce}}),jQuery(this).parents("li").hide(),!1}),jQuery(document.body).on("click",".um-reset-cover-photo",function(e){var t=jQuery(this);return jQuery(".um-cover-overlay").hide(),jQuery(".um-cover-e").html('<a href="javascript:void(0);" class="um-cover-add" style="height: 370px;"><span class="um-cover-add-i"><i class="um-icon-plus um-tip-n" title="Upload a cover photo"></i></span></a>'),um_responsive(),user_id=jQuery(this).attr("data-user_id"),metakey="cover_photo",jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_cover_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce},success:function(e){t.hide()}}),UM.dropdown.hideAll(),!1}),jQuery(document.body).on("change keyup","#um-meta-bio",function(){if(void 0!==jQuery(this).val()){var t=jQuery(this).data("character-limit"),r=jQuery(this).data("html");let e=t-jQuery(this).val().length;e=(e=1===parseInt(r)?t-jQuery(this).val().replace(/(<([^>]+)>)/gi,"").length:e)<0?0:e,jQuery("span.um-meta-bio-character span.um-bio-limit").text(e);r=e<5?"red":"";jQuery("span.um-meta-bio-character").css("color",r)}}),jQuery("#um-meta-bio").trigger("change"),jQuery(".um-profile form").each(function(){let t=jQuery(this).data("description_key");jQuery(this).find('textarea[name="'+t+'"]').length&&jQuery(document.body).on("change input",'textarea[name="'+t+'"]',function(e){jQuery(this).parents("form").find('textarea[name="'+t+'"]').each(function(){jQuery(this).val(e.currentTarget.value),jQuery("#um-meta-bio")[0]!==e.currentTarget&&jQuery("#um-meta-bio")[0]===jQuery(this)[0]&&jQuery(this).trigger("change")})})}),jQuery(".um-profile-edit a.um_delete-item").on("click",function(e){if(e.preventDefault(),!confirm(wp.i18n.__("Are you sure that you want to delete this user?","ultimate-member")))return!1}),jQuery(".um-profile-nav a").on("touchend",function(e){jQuery(e.currentTarget).trigger("click")})});
+1
View File
@@ -21,6 +21,7 @@
"ext-fileinfo": "*",
"ext-curl": "*",
"ext-iconv": "*",
"ext-tidy": "*",
"woocommerce/action-scheduler": "3.2.1"
},
"require-dev": {
+63
View File
@@ -736,6 +736,59 @@ if ( ! class_exists( 'um\core\Form' ) ) {
return $form;
}
/**
* Use PHP tidy extension if it's active for getting clean HTML without unclosed tags.
*
* @param string $html_fragment Textarea with active HTML option field value.
* @param array $field_data Ultimate Member form field data.
*
* @return string|\tidy
*/
private static function maybe_apply_tidy( $html_fragment, $field_data ) {
// Break if extension isn't active in php.ini
if ( ! function_exists( 'tidy_parse_string' ) ) {
return $html_fragment;
}
$tidy_config = array(
'clean' => true,
'output-xhtml' => true,
'show-body-only' => true,
'wrap' => 0,
);
/**
* Filters PHP tidy extension config.
* Get more info here https://www.php.net/manual/en/tidy.parsestring.php
*
* @param {array} $tidy_config Config.
* @param {array} $field_data UM Form Field Data.
*
* @return {array} Config.
*
* @since 2.8.9
* @hook um_tidy_config
*
* @example <caption>Customize tidy config based on field data.</caption>
* function my_um_tidy_config( $tidy_config, $field_data ) {
* // your code here
* if ( 'custom_metakey' === $field_data['metakey'] ) {
* $tidy_config['clean'] = false;
* }
* return $tidy_config;
* }
* add_filter( 'um_tidy_config', 'my_um_tidy_config', 10, 2 );
*/
$tidy_config = apply_filters( 'um_tidy_config', $tidy_config, $field_data );
// since PHP8.0 $tidy_config, 'UTF8' variables are nullable https://www.php.net/manual/en/tidy.parsestring.php
$tidy = tidy_parse_string( $html_fragment, $tidy_config, 'UTF8' );
$result = $tidy->cleanRepair();
if ( $result ) {
return $tidy;
}
return $html_fragment;
}
/**
* Beautify form data
@@ -770,6 +823,8 @@ if ( ! class_exists( 'um\core\Form' ) ) {
$form[ $k ] = $match[1];
}
$form[ $k ] = self::maybe_apply_tidy( $form[ $k ], $field );
$allowed_html = UM()->get_allowed_html( 'templates' );
if ( empty( $allowed_html['iframe'] ) ) {
$allowed_html['iframe'] = array(
@@ -907,6 +962,14 @@ if ( ! class_exists( 'um\core\Form' ) ) {
if ( array_key_exists( $description_key, $custom_fields ) ) {
$field_exists = true;
if ( ! empty( $custom_fields[ $description_key ]['html'] ) && $bio_html ) {
$form[ $description_key ] = html_entity_decode( $form[ $description_key ] ); // required because WP_Editor send sometimes encoded content.
preg_match( '/^<p>(.*?)<\/p>$/', $form[ $description_key ], $match ); // required because WP_Editor send content wrapped to <p></p>
if ( ! empty( $match[1] ) ) {
$form[ $description_key ] = $match[1];
}
$form[ $description_key ] = self::maybe_apply_tidy( $form[ $description_key ], $custom_fields[ $description_key ] );
$allowed_html = UM()->get_allowed_html( 'templates' );
if ( empty( $allowed_html['iframe'] ) ) {
$allowed_html['iframe'] = array(
+1 -1
View File
@@ -261,7 +261,7 @@ function um_profile_field_filter_hook__textarea( $value, $data ) {
}
if ( ! empty( $data['html'] ) ) {
return '<iframe class="um-textarea-html-value" onload="UM.frontend.iframe.resize(this);" title="' . esc_attr( $data['label'] ) . '" srcdoc="' . wp_kses_post( esc_attr( $value ) ) . '"></iframe>';
return wp_kses_post( $value );
}
$description_key = UM()->profile()->get_show_bio_key( UM()->fields()->global_args );
+12
View File
@@ -166,6 +166,18 @@ No specific extensions are needed. But we highly recommended keep active these P
IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
= 2.8.9 2024-10-14 =
**Enhancements**
* Added: Using PHP tidy extension (if it's active) to make HTML textarea value clear
* Added: `um_tidy_config` filter hook for setting PHP tidy config
**Bugfixes**
* Fixed: UM tipsy removing inside .um-page selector (e.g. tipsy init from um-modal)
* Fixed: Rollback using `<iframe>` for displaying HTML formatted textarea value
= 2.8.8 2024-10-04 =
**Bugfixes**