Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/lifterlms/class-lifterlms.php
+++ b/lifterlms/class-lifterlms.php
@@ -34,7 +34,7 @@
*
* @var string
*/
- public $version = '9.2.1';
+ public $version = '9.2.2';
/**
* LLMS_Assets instance
--- a/lifterlms/includes/abstracts/abstract.llms.admin.table.php
+++ b/lifterlms/includes/abstracts/abstract.llms.admin.table.php
@@ -372,8 +372,10 @@
public function get_filter_placeholder( $column_id, $column_data ) {
$placeholder = __( 'Any', 'lifterlms' );
if ( is_array( $column_data ) && isset( $column_data['title'] ) ) {
+ /* translators: %s: Column title. */
$placeholder = sprintf( __( 'Any %s', 'lifterlms' ), $column_data['title'] );
} elseif ( is_string( $column_data ) ) {
+ /* translators: %s: Column title. */
$placeholder = sprintf( __( 'Any %s', 'lifterlms' ), $column_data );
}
/**
@@ -793,7 +795,7 @@
<form action="" method="POST">
<button class="llms-button-primary small" name="llms_quiz_resumable_attempt_action" type="submit" value="llms_clear_resumable_attempts">
<i class="fa fa-trash-o" aria-hidden="true"></i>
- <?php _e( 'Clear resumable attempts', 'lifterlms' ); ?>
+ <?php echo esc_html( __( 'Clear resumable attempts', 'lifterlms' ) ); ?>
</button>
<input type="hidden" name="llms_quiz_id" value="<?php echo esc_attr( $this->quiz_id ); ?>">
<?php wp_nonce_field( 'llms_quiz_attempt_actions', '_llms_quiz_attempt_nonce' ); ?>
@@ -814,7 +816,12 @@
<?php if ( $this->is_paginated ) : ?>
<div class="llms-table-pagination">
<?php if ( $this->max_pages ) : ?>
- <span class="llms-table-page-count"><?php echo esc_html( sprintf( esc_html_x( '%1$d of %2$d', 'pagination', 'lifterlms' ), $this->current_page, $this->max_pages ) ); ?></span>
+ <span class="llms-table-page-count">
+ <?php
+ /* translators: %1$d: Current page, %2$d: Total page count. */
+ echo esc_html( sprintf( esc_html_x( '%1$d of %2$d', 'pagination', 'lifterlms' ), $this->current_page, $this->max_pages ) );
+ ?>
+ </span>
<?php endif; ?>
<?php if ( 1 !== $this->get_current_page() ) : ?>
<?php if ( $this->max_pages ) : ?>
--- a/lifterlms/includes/abstracts/abstract.llms.database.query.php
+++ b/lifterlms/includes/abstracts/abstract.llms.database.query.php
@@ -397,6 +397,7 @@
} else {
_doing_it_wrong(
__METHOD__,
+ /* translators: %s: Method name. */
esc_html( sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'lifterlms' ), __METHOD__ ) ),
'6.0.0'
);
--- a/lifterlms/includes/abstracts/abstract.llms.payment.gateway.php
+++ b/lifterlms/includes/abstracts/abstract.llms.payment.gateway.php
@@ -362,6 +362,7 @@
$fields[] = array(
'autoload' => true,
'id' => $this->get_option_name( 'enabled' ),
+ /* translators: %s: Payment gateway title. */
'desc' => sprintf( _x( 'Enable %s', 'Payment gateway title', 'lifterlms' ), $this->get_admin_title() ),
'desc_tooltip' => __( 'Checking this box will allow users to use this payment gateway.', 'lifterlms' ),
'default' => $this->get_enabled(),
@@ -389,6 +390,7 @@
$fields[] = array(
'id' => $this->get_option_name( 'test_mode_enabled' ),
+ /* translators: %s: Payment gateway test mode title. */
'desc' => sprintf( _x( 'Enable %s', 'Payment gateway test mode title', 'lifterlms' ), $this->get_test_mode_title() ),
'desc_tooltip' => $this->get_test_mode_description(),
'default' => $this->get_test_mode_enabled(),
@@ -401,6 +403,7 @@
$fields[] = array(
'id' => $this->get_option_name( 'logging_enabled' ),
'desc' => __( 'Enable debug logging', 'lifterlms' ),
+ /* Translators: %s: Debug log location. */
'desc_tooltip' => sprintf( __( 'When enabled, debugging information will be logged to "%s"', 'lifterlms' ), llms_get_log_path( $this->get_id() ) ),
'title' => __( 'Debug Log', 'lifterlms' ),
'type' => 'checkbox',
@@ -803,7 +806,7 @@
public function handle_payment_source_switch( $order, $form_data = array() ) {
return llms_add_notice(
sprintf(
- // Translatos: %s = the title of the payment gateway.
+ /* translators: %s: the title of the payment gateway. */
esc_html__( 'The selected payment gateway "%s" does not support payment method switching.', 'lifterlms' ),
$this->get_title()
),
--- a/lifterlms/includes/abstracts/abstract.llms.post.model.php
+++ b/lifterlms/includes/abstracts/abstract.llms.post.model.php
@@ -724,7 +724,7 @@
if ( 'html' === $format || 'raw' === $format ) {
$price = llms_price( $price, $price_args );
if ( 'raw' === $format ) {
- $price = strip_tags( $price );
+ $price = wp_strip_all_tags( $price );
}
} elseif ( 'float' === $format ) {
$price = floatval( number_format( $price, get_lifterlms_decimals(), '.', '' ) );
@@ -855,7 +855,7 @@
$prop = $prop ? $prop : $type . '_embed';
$url = $this->get( $prop );
- if ( trim( $url ) && parse_url( $url ) ) {
+ if ( trim( $url ) && wp_parse_url( $url ) ) {
$this->get_provider_support( $url );
$ret = wp_oembed_get( sanitize_url( $url ) );
@@ -1516,6 +1516,7 @@
$u = update_post_meta( $this->id, $this->meta_prefix . $key, wp_slash( $val ) );
if ( ! ( is_numeric( $u ) || true === $u ) ) {
+ /* translators: %s: Meta key. */
$error->add( 'invalid_meta', sprintf( __( 'Cannot insert/update the %s meta', 'lifterlms' ), $key ) );
}
}
--- a/lifterlms/includes/abstracts/abstract.llms.update.php
+++ b/lifterlms/includes/abstracts/abstract.llms.update.php
@@ -73,7 +73,6 @@
break;
}
-
}
/**
@@ -90,7 +89,6 @@
add_action( $this->get_hook( $func ), array( $this, $func ), 10, 1 );
}
-
}
/**
@@ -116,7 +114,6 @@
$this->log( sprintf( 'Progress: %d completed, %d remaining', $completed, $remaining ) );
}
-
}
/**
@@ -132,7 +129,6 @@
$this->log( sprintf( 'LLMS update tasks completed for version %s', $this->version ) );
LLMS_Install::update_db_version( $this->version );
delete_option( 'llms_update_' . $this->version );
-
}
/**
@@ -150,7 +146,6 @@
}
$this->log( sprintf( 'LLMS update tasks enqueued for version %s', $this->version ) );
-
}
/**
@@ -168,7 +163,6 @@
$progress['functions'][ $function ] = 'done';
update_option( 'llms_update_' . $this->version, $progress );
$this->log( sprintf( '%s::%s() is complete', get_class( $this ), $function ) );
-
}
/**
@@ -198,7 +192,6 @@
);
return get_option( 'llms_update_' . $this->version, $default );
-
}
/**
@@ -242,7 +235,6 @@
$p = $this->get_progress();
$p['status'] = $status;
update_option( 'llms_update_' . $this->version, $p );
-
}
/**
@@ -258,7 +250,6 @@
if ( defined( 'LLMS_BG_UPDATE_LOG' ) && LLMS_BG_UPDATE_LOG ) {
llms_log( $msg, 'updater' );
}
-
}
@@ -283,9 +274,13 @@
$max = count( $progress['functions'] );
$width = $val ? ( $val / $max ) * 100 : 0;
$html = '
- <p>' . sprintf( __( 'LifterLMS Database Upgrade %s Progress Report', 'lifterlms' ), $this->version ) . '</p>
+ ';
+ /* translators: %s: Database version. */
+ $html .= '<p>' . sprintf( __( 'LifterLMS Database Upgrade %s Progress Report', 'lifterlms' ), $this->version ) . '</p>
<div style="background:#efefef;height:18px;margin:0.5em 0;"><div style="background:#ef476f;display:block;height:18px;width:' . $width . '%;"><span style="padding:0 0.5em;color:#fff;">' . $width . '%</span></div></div>
- <p><em>' . sprintf( __( 'This completion percentage is an estimate, please be patient and %1$sclick here%2$s for more information.', 'lifterlms' ), '<a href="https://lifterlms.com/docs/lifterlms-database-updates/#upgrade-progress-report" target="_blank">', '</a>' ) . '</em></p>
+ ';
+ /* translators: %1$s: Opening link tag, %2$s: closing link tag. */
+ $html .= '<p><em>' . sprintf( __( 'This completion percentage is an estimate, please be patient and %1$sclick here%2$s for more information.', 'lifterlms' ), '<a href="https://lifterlms.com/docs/lifterlms-database-updates/#upgrade-progress-report" target="_blank">', '</a>' ) . '</em></p>
';
LLMS_Admin_Notices::add_notice(
@@ -297,7 +292,5 @@
'type' => 'info',
)
);
-
}
-
}
--- a/lifterlms/includes/abstracts/llms-abstract-email-provider.php
+++ b/lifterlms/includes/abstracts/llms-abstract-email-provider.php
@@ -326,9 +326,9 @@
}
if ( ! $this->is_installed() ) {
- // Translators: %s = title of the email delivery plugin.
return array(
'code' => 'llms_' . $this->id . '_not_found',
+ /* translators: %s: title of the email delivery plugin. */
'message' => sprintf( __( '%s plugin not found. Please try again.', 'lifterlms' ), $this->get_title() ),
'status' => 400,
);
--- a/lifterlms/includes/abstracts/llms-abstract-generator-posts.php
+++ b/lifterlms/includes/abstracts/llms-abstract-generator-posts.php
@@ -171,6 +171,7 @@
$class_name = sprintf( 'LLMS_%s', implode( '_', array_map( 'ucfirst', explode( '_', $type ) ) ) );
if ( ! class_exists( $class_name ) ) {
+ /* translators: %s: Name of class. */
throw new Exception( esc_html( sprintf( __( 'The class "%s" does not exist.', 'lifterlms' ), $class_name ) ), intval( self::ERROR_INVALID_POST ) );
}
@@ -514,6 +515,7 @@
$term = wp_insert_term( $term_name, $tax );
if ( is_wp_error( $term ) ) {
+ /* translators: %s: name of term. */
throw new Exception( esc_html( sprintf( __( 'Error creating new term "%s".', 'lifterlms' ), $term_name ) ), intval( self::ERROR_CREATE_TERM ) );
}
@@ -811,7 +813,7 @@
$blocked_hosts = apply_filters(
'llms_generator_sideload_hosts_blocklist',
array(
- parse_url( get_site_url(), PHP_URL_HOST ),
+ wp_parse_url( get_site_url(), PHP_URL_HOST ),
)
);
@@ -821,7 +823,7 @@
foreach ( $raw['_extras']['images'] as $src ) {
// Don't sideload images from blocked hosts.
- if ( in_array( parse_url( $src, PHP_URL_HOST ), $blocked_hosts, true ) ) {
+ if ( in_array( wp_parse_url( $src, PHP_URL_HOST ), $blocked_hosts, true ) ) {
continue;
}
--- a/lifterlms/includes/abstracts/llms-abstract-meta-box-user-engagement-sync.php
+++ b/lifterlms/includes/abstracts/llms-abstract-meta-box-user-engagement-sync.php
@@ -259,7 +259,7 @@
// Output the HTML.
echo '<div class="llms-mb-container">';
do_action( 'llms_metabox_before_content', $this->id );
- echo wp_kses_post( $sync_action );
+ echo wp_kses( $sync_action, LLMS_ALLOWED_HTML_FORM_FIELDS );
do_action( 'llms_metabox_after_content', $this->id );
echo '</div>';
}
@@ -290,16 +290,15 @@
);
$sync_alert = str_replace( "'", "'", $texts['sync_alert'] );
- $on_click = "return confirm('$sync_alert')";
$button_label = __( 'Sync', 'lifterlms' );
- return <<<HEREDOC
-
-<p>{$texts['sync_description']}</p>
+ ob_start();
+ ?>
+<p><?php echo wp_kses_post( $texts['sync_description'] ); ?></p>
<p style="text-align: right; margin: 1em 0;">
-<a href="$sync_url" class="llms-button-primary sync-action full small" onclick="$on_click" style="box-sizing:border-box;">$button_label</a>
+<a href="<?php echo esc_url( $sync_url ); ?>" class="llms-button-primary sync-action full small" onclick="return confirm('<?php echo esc_js( $sync_alert ); ?>')" style="box-sizing:border-box;"><?php echo wp_kses_post( $button_label ); ?></a>
</p>
-
-HEREDOC;
+ <?php
+ return ob_get_clean();
}
}
--- a/lifterlms/includes/abstracts/llms.abstract.exportable.admin.table.php
+++ b/lifterlms/includes/abstracts/llms.abstract.exportable.admin.table.php
@@ -164,7 +164,7 @@
* @return mixed
*/
public function get_export_data( $key, $data ) {
- return trim( strip_tags( $this->get_data( $key, $data ) ) );
+ return trim( wp_strip_all_tags( $this->get_data( $key, $data ) ) );
}
/**
--- a/lifterlms/includes/abstracts/llms.abstract.notification.view.php
+++ b/lifterlms/includes/abstracts/llms.abstract.notification.view.php
@@ -341,6 +341,7 @@
if ( ( $now - $created ) <= ( $max_days * DAY_IN_SECONDS ) ) {
+ /* translators: %s: Relative date display. */
return sprintf( _x( 'About %s ago', 'relative date display', 'lifterlms' ), $this->get_date_relative( 'created' ) );
}
--- a/lifterlms/includes/admin/class-llms-admin-review.php
+++ b/lifterlms/includes/admin/class-llms-admin-review.php
@@ -87,7 +87,7 @@
// Conditionally filter footer text with our content.
if ( ! empty( $show_footer ) ) {
- $url = 'https://wordpress.org/support/plugin/lifterlms/reviews/?filter=5#new-post';
+ $url = 'https://wordpress.org/support/plugin/lifterlms/reviews/#new-post';
$text = sprintf(
wp_kses(
/* Translators: %1$s = LifterLMS plugin name; %2$s = WP.org review link; %3$s = WP.org review link. */
--- a/lifterlms/includes/admin/post-types/class.llms.post.tables.php
+++ b/lifterlms/includes/admin/post-types/class.llms.post.tables.php
@@ -155,7 +155,7 @@
if ( ! $r ) {
LLMS_Admin_Notices::flash_notice( esc_html__( 'There was an error detaching the post.', 'lifterlms' ), 'error' );
}
- wp_redirect( admin_url( 'edit.php?post_type=' . $post->get( 'type' ) ) );
+ wp_safe_redirect( admin_url( 'edit.php?post_type=' . $post->get( 'type' ) ) );
exit;
case 'llms-clone-post':
@@ -166,7 +166,7 @@
if ( is_wp_error( $r ) ) {
LLMS_Admin_Notices::flash_notice( $r->get_error_message(), 'error' );
}
- wp_redirect( admin_url( 'edit.php?post_type=' . $post->get( 'type' ) ) );
+ wp_safe_redirect( admin_url( 'edit.php?post_type=' . $post->get( 'type' ) ) );
exit;
}
--- a/lifterlms/includes/admin/post-types/meta-boxes/class-llms-meta-box-achievement-sync.php
+++ b/lifterlms/includes/admin/post-types/meta-boxes/class-llms-meta-box-achievement-sync.php
@@ -72,7 +72,7 @@
return sprintf(
/* translators: %1$d: number of awarded achievements */
__(
- 'This action will replace the current title, content, background etc. of %1$d awarded achievements with the ones from this achievement template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of %1$d awarded achievements with the ones from this achievement template. Are you sure you want to proceed?',
'lifterlms'
),
( $variables['awarded_number'] ?? 0 )
@@ -81,14 +81,14 @@
return sprintf(
/* translators: %1$d: number of awarded achievements */
__(
- 'This action will replace the current title, content, background etc. of %1$d awarded achievement with the ones from this achievement template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of %1$d awarded achievement with the ones from this achievement template. Are you sure you want to proceed?',
'lifterlms'
),
( $variables['awarded_number'] ?? 0 )
);
case self::TEXT_SYNC_ALERT_THIS_AWARDED_ENGAGEMENT:
return __(
- 'This action will replace the current title, content, background etc. of this awarded achievement with the ones from the achievement template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of this awarded achievement with the ones from the achievement template. Are you sure you want to proceed?',
'lifterlms'
);
case self::TEXT_SYNC_DESCRIPTION_MANY_AWARDED_ENGAGEMENTS:
--- a/lifterlms/includes/admin/post-types/meta-boxes/class-llms-meta-box-certificate-sync.php
+++ b/lifterlms/includes/admin/post-types/meta-boxes/class-llms-meta-box-certificate-sync.php
@@ -72,7 +72,7 @@
return sprintf(
/* translators: %1$d: number of awarded certificates */
__(
- 'This action will replace the current title, content, background etc. of %1$d awarded certificates with the ones from this certificate template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of %1$d awarded certificates with the ones from this certificate template. Are you sure you want to proceed?',
'lifterlms'
),
( $variables['awarded_number'] ?? 0 )
@@ -81,14 +81,14 @@
return sprintf(
/* translators: %1$d: number of awarded certificates */
__(
- 'This action will replace the current title, content, background etc. of %1$d awarded certificate with the ones from this certificate template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of %1$d awarded certificate with the ones from this certificate template. Are you sure you want to proceed?',
'lifterlms'
),
( $variables['awarded_number'] ?? 0 )
);
case self::TEXT_SYNC_ALERT_THIS_AWARDED_ENGAGEMENT:
return __(
- 'This action will replace the current title, content, background etc. of this awarded certificate with the ones from the certificate template.nAre you sure you want to proceed?',
+ 'This action will replace the current title, content, background etc. of this awarded certificate with the ones from the certificate template. Are you sure you want to proceed?',
'lifterlms'
);
case self::TEXT_SYNC_DESCRIPTION_MANY_AWARDED_ENGAGEMENTS:
--- a/lifterlms/includes/admin/reporting/tables/llms.table.quiz.non.attempts.php
+++ b/lifterlms/includes/admin/reporting/tables/llms.table.quiz.non.attempts.php
@@ -185,9 +185,10 @@
$this->current_page = absint( $args['page'] );
}
- $per = apply_filters( 'llms_reporting_' . $this->id . '_per_page', 25 );
+ $per = apply_filters( 'llms_reporting_' . $this->id . '_per_page', 25 );
+ $order = isset( $args['order'] ) ? $args['order'] : $this->order;
+ $this->order = in_array( $order, array( 'ASC', 'DESC' ), true ) ? $order : 'ASC';
- $this->order = isset( $args['order'] ) ? $args['order'] : $this->order;
$this->orderby = isset( $args['orderby'] ) ? $args['orderby'] : $this->orderby;
$this->filter = isset( $args['filter'] ) ? $args['filter'] : $this->get_filter();
--- a/lifterlms/includes/admin/views/access-plans/access-plan.php
+++ b/lifterlms/includes/admin/views/access-plans/access-plan.php
@@ -275,7 +275,7 @@
<input
id="_llms_plans[<?php echo esc_attr( $order ); ?>][price]"
class="llms-plan-price" name="_llms_plans[<?php echo esc_attr( $order ); ?>][price]"
- placeholder="<?php echo esc_attr( strip_tags( llms_price( 1000 ) ) ); ?>"
+ placeholder="<?php echo esc_attr( wp_strip_all_tags( llms_price( 1000 ) ) ); ?>"
<?php if ( apply_filters( 'llms_access_plan_price_required', true, $plan ) ) : ?>
min="<?php echo esc_attr( $price_step ); ?>"
required="required"
@@ -475,7 +475,7 @@
<i class="fa fa-question-circle"></i>
</span>
</label>
- <input id="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_price]" name="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_price]" min="0" placeholder="<?php echo esc_attr( strip_tags( llms_price( 1000 ) ) ); ?>" required="required" step="<?php echo esc_attr( $price_step ); ?>" type="text"<?php echo ( $plan ) ? ' value="' . esc_attr( $plan->get( 'trial_price' ) ) . '"' : ' disabled="disabled"'; ?>>
+ <input id="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_price]" name="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_price]" min="0" placeholder="<?php echo esc_attr( wp_strip_all_tags( llms_price( 1000 ) ) ); ?>" required="required" step="<?php echo esc_attr( $price_step ); ?>" type="text"<?php echo ( $plan ) ? ' value="' . esc_attr( $plan->get( 'trial_price' ) ) . '"' : ' disabled="disabled"'; ?>>
</div>
<div class="llms-metabox-field d-1of4" data-controller="llms-trial-offer" data-value-is="yes">
@@ -490,14 +490,14 @@
</div>
<div class="llms-metabox-field d-1of4" data-controller="llms-trial-offer" data-value-is="yes">
- <label for="_llms_plans[<?php echo $order; ?>][trial_period]">
+ <label for="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_period]">
<?php esc_html_e( 'Trial Period', 'lifterlms' ); ?>
<span class="screen-reader-text"><?php esc_html_e( 'Define the time length for the trial period (days, weeks, months, years).', 'lifterlms' ); ?></span>
<span class="tip--top-right" data-tip="<?php esc_attr_e( 'Define the time length for the trial period (days, weeks, months, years).', 'lifterlms' ); ?>">
<i class="fa fa-question-circle"></i>
</span>
</label>
- <select id="_llms_plans[<?php echo $order; ?>][trial_period]" name="_llms_plans[<?php echo $order; ?>][trial_period]"<?php echo ( $plan ) ? '' : ' disabled="disabled"'; ?>>
+ <select id="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_period]" name="_llms_plans[<?php echo esc_attr( $order ); ?>][trial_period]"<?php echo ( $plan ) ? '' : ' disabled="disabled"'; ?>>
<option value="year"<?php selected( 'year', ( $plan && 'yes' === $trial_offer ) ? $plan->get( 'trial_period' ) : '' ); ?>><?php esc_html_e( 'year(s)', 'lifterlms' ); ?></option>
<option value="month"<?php selected( 'month', ( $plan && 'yes' === $trial_offer ) ? $plan->get( 'trial_period' ) : '' ); ?>><?php esc_html_e( 'month(s)', 'lifterlms' ); ?></option>
<option value="week"<?php selected( 'week', ( $plan && 'yes' === $trial_offer ) ? $plan->get( 'trial_period' ) : '' ); ?>><?php esc_html_e( 'week(s)', 'lifterlms' ); ?></option>
@@ -546,7 +546,7 @@
<i class="fa fa-question-circle"></i>
</span>
</label>
- <input id="_llms_plans[<?php echo esc_attr( $order ); ?>][sale_price]" name="_llms_plans[<?php echo esc_attr( $order ); ?>][sale_price]" min="0" placeholder="<?php echo esc_attr( strip_tags( llms_price( 1000 ) ) ); ?>" required="required" step="<?php echo esc_attr( $price_step ); ?>" type="number"<?php echo ( $plan && 'yes' === $on_sale ) ? ' value="' . esc_attr( $plan->get( 'sale_price' ) ) . '"' : ' disabled="disabled"'; ?>>
+ <input id="_llms_plans[<?php echo esc_attr( $order ); ?>][sale_price]" name="_llms_plans[<?php echo esc_attr( $order ); ?>][sale_price]" min="0" placeholder="<?php echo esc_attr( wp_strip_all_tags( llms_price( 1000 ) ) ); ?>" required="required" step="<?php echo esc_attr( $price_step ); ?>" type="number"<?php echo ( $plan && 'yes' === $on_sale ) ? ' value="' . esc_attr( $plan->get( 'sale_price' ) ) . '"' : ' disabled="disabled"'; ?>>
</div>
<div class="llms-metabox-field d-1of4" data-controller="llms-on-sale" data-value-is="yes">
@@ -615,7 +615,7 @@
<i class="fa fa-question-circle"></i>
</span>
</label>
- <select data-controller-id="llms-availability" name="_llms_plans[<?php echo $order; ?>][availability]"<?php echo ( $plan ) ? '' : ' disabled="disabled"'; ?>>
+ <select data-controller-id="llms-availability" name="_llms_plans[<?php echo esc_attr( $order ); ?>][availability]"<?php echo ( $plan ) ? '' : ' disabled="disabled"'; ?>>
<option value="open"<?php selected( 'open', $plan ? $availability : '' ); ?>><?php esc_html_e( 'Anyone', 'lifterlms' ); ?></option>
<option value="members"<?php selected( 'members', $plan ? $availability : '' ); ?>><?php esc_html_e( 'Members only', 'lifterlms' ); ?></option>
</select>
--- a/lifterlms/includes/admin/views/notices/review-request.php
+++ b/lifterlms/includes/admin/views/notices/review-request.php
@@ -22,7 +22,7 @@
<p><?php esc_html_e( 'Could you please do us a BIG favor and give LifterLMS a 5-star rating on WordPress to help us grow?', 'lifterlms' ); ?></p>
<p>– <?php esc_html_e( 'Chris Badgett, CEO of LifterLMS', 'lifterlms' ); ?></p>
<p>
- <a href="https://wordpress.org/support/plugin/lifterlms/reviews/?filter=5#new-post" class="llms-button-primary small llms-review-notice-dismiss llms-review-notice-out" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Ok, you deserve it', 'lifterlms' ); ?></a>
+ <a href="https://wordpress.org/support/plugin/lifterlms/reviews/#new-post" class="llms-button-primary small llms-review-notice-dismiss llms-review-notice-out" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Ok, you deserve it', 'lifterlms' ); ?></a>
<button class="llms-button-secondary small llms-review-notice-dismiss"><?php esc_html_e( 'Nope, maybe later', 'lifterlms' ); ?></button>
<button class="llms-button-secondary small llms-review-notice-dismiss"><?php esc_html_e( 'I already did', 'lifterlms' ); ?></button>
</p>
--- a/lifterlms/includes/class-llms-dom-document.php
+++ b/lifterlms/includes/class-llms-dom-document.php
@@ -126,14 +126,16 @@
}
/**
- * Load the HTML string in the DOMDocument using mb_convert_econding
+ * Load the HTML string in the DOMDocument using mb_encode_numericentity
*
* @since 4.13.0
+ * @since 9.2.2 Use `mb_encode_numericentity()` instead of deprecated `mb_convert_encoding()` with 'HTML-ENTITIES'.
*
* @return void
*/
private function load_with_mb_convert_encoding() {
- if ( ! $this->dom->loadHTML( mb_convert_encoding( $this->source, 'HTML-ENTITIES', 'UTF-8' ) ) ) {
+ $html = mb_encode_numericentity( $this->source, array( 0x80, 0x10FFFF, 0, 0x1FFFFF ), 'UTF-8' );
+ if ( ! $this->dom->loadHTML( $html ) ) {
$this->error = new WP_Error( 'llms-dom-document-error', __( 'DOMDocument XML Error encountered.', 'lifterlms' ), libxml_get_errors() );
}
}
--- a/lifterlms/includes/class-llms-media-protector.php
+++ b/lifterlms/includes/class-llms-media-protector.php
@@ -356,7 +356,7 @@
*/
protected function get_size() {
- $size = ( isset( $_GET[ self::URL_PARAMETER_SIZE ] ) ) ? sanitize_text_field( $_GET[ self::URL_PARAMETER_SIZE ] ) : null;
+ $size = ( isset( $_GET[ self::URL_PARAMETER_SIZE ] ) ) ? sanitize_text_field( wp_unslash( $_GET[ self::URL_PARAMETER_SIZE ] ) ) : null;
if ( false === $size ) {
$size = null;
} elseif ( is_string( $size ) && '[' === $size[0] ) {
@@ -534,7 +534,7 @@
$is_modified = true;
$file_modified = filemtime( $file_name );
- $if_modified_since = ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) ? sanitize_text_field( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) : '';
+ $if_modified_since = ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) : '';
if ( strtotime( $if_modified_since ) === $file_modified ) {
$is_modified = false;
}
@@ -733,7 +733,7 @@
* @return void
*/
protected function send_file( $file_name, $media_id ) {
- $server_software = ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( $_SERVER['SERVER_SOFTWARE'] ) : '' );
+ $server_software = ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '' );
if (
( array_key_exists( 'MOD_X_SENDFILE_ENABLED', $_SERVER ) && '1' === $_SERVER['MOD_X_SENDFILE_ENABLED'] ) ||
@@ -826,7 +826,7 @@
}
protected function strip_query_params( $file_name ) {
- $parsed_url = parse_url( $file_name );
+ $parsed_url = wp_parse_url( $file_name );
$path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : $file_name;
return $path;
}
@@ -893,7 +893,7 @@
if ( ! isset( $size ) ) {
$size = $this->get_size();
}
- $icon = ( isset( $_GET[ self::URL_PARAMETER_ICON ] ) ? sanitize_text_field( $_GET[ self::URL_PARAMETER_ICON ] ) : null );
+ $icon = ( isset( $_GET[ self::URL_PARAMETER_ICON ] ) ? sanitize_text_field( wp_unslash( $_GET[ self::URL_PARAMETER_ICON ] ) ) : null );
if ( ! is_null( $size ) || $icon ) {
$image = wp_get_attachment_image_src( $media_id, $size, $icon );
$file_name = dirname( $file_name ) . '/' . basename( $image[0] );
--- a/lifterlms/includes/class.llms.course.data.php
+++ b/lifterlms/includes/class.llms.course.data.php
@@ -130,7 +130,7 @@
global $wpdb;
- $ids = implode( ',', $this->get_all_ids() );
+ $ids = implode( ',', array_map( 'absint', $this->get_all_ids() ) );
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $wpdb->get_var(
@@ -163,14 +163,16 @@
global $wpdb;
- $lessons = implode( ',', $this->post->get_lessons( 'ids' ) );
- // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $lesson_ids = $this->post->get_lessons( 'ids' );
// Return early for courses without any lessons.
- if ( empty( $lessons ) ) {
+ if ( empty( $lesson_ids ) ) {
return 0;
}
+ $lessons = implode( ',', array_map( 'absint', $this->post->get_lessons( 'ids' ) ) );
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+
return $wpdb->get_var(
$wpdb->prepare(
"
@@ -229,7 +231,7 @@
if ( $order_ids ) {
- $order_ids = implode( ',', $order_ids );
+ $order_ids = implode( ',', array_map( 'absint', $order_ids ) );
global $wpdb;
$revenue = $wpdb->get_var(
--- a/lifterlms/includes/class.llms.post-types.php
+++ b/lifterlms/includes/class.llms.post-types.php
@@ -180,12 +180,14 @@
// Single payment only.
'llms-completed' => array(
'label' => _x( 'Completed', 'Order status', 'lifterlms' ),
+ /* translators: %s: Completed count, %s: Completed count. */
'label_count' => _n_noop( 'Completed <span class="count">(%s)</span>', 'Completed <span class="count">(%s)</span>', 'lifterlms' ),
),
// Recurring only.
'llms-active' => array(
'label' => _x( 'Active', 'Order status', 'lifterlms' ),
+ /* translators: %s: Active count, %s: Active count. */
'label_count' => _n_noop( 'Active <span class="count">(%s)</span>', 'Active <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-expired' => array(
@@ -194,6 +196,7 @@
),
'llms-on-hold' => array(
'label' => _x( 'On Hold', 'Order status', 'lifterlms' ),
+ /* translators: %s: On hold count, %s: On hold count. */
'label_count' => _n_noop( 'On Hold <span class="count">(%s)</span>', 'On Hold <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-pending-cancel' => array(
@@ -204,18 +207,22 @@
// Shared.
'llms-pending' => array(
'label' => _x( 'Pending Payment', 'Order status', 'lifterlms' ),
+ /* translators: %s: Pending Payment count, %s: Pending Payment count. */
'label_count' => _n_noop( 'Pending Payment <span class="count">(%s)</span>', 'Pending Payment <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-cancelled' => array(
'label' => _x( 'Cancelled', 'Order status', 'lifterlms' ),
+ /* translators: %s: Cancelled count, %s: Cancelled count. */
'label_count' => _n_noop( 'Cancelled <span class="count">(%s)</span>', 'Cancelled <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-refunded' => array(
'label' => _x( 'Refunded', 'Order status', 'lifterlms' ),
+ /* translators: %s: Refunded count, %s: Refunded count. */
'label_count' => _n_noop( 'Refunded <span class="count">(%s)</span>', 'Refunded <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-failed' => array(
'label' => _x( 'Failed', 'Order status', 'lifterlms' ),
+ /* translators: %s: Failed count, %s: Failed count. */
'label_count' => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>', 'lifterlms' ),
),
@@ -1229,6 +1236,7 @@
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
+ /* translators: %s: Failed count, %s: Failed count. */
'label_count' => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-txn-pending' => array(
@@ -1237,6 +1245,7 @@
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
+ /* translators: %s: Pending count, %s: Pending count. */
'label_count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-txn-refunded' => array(
@@ -1245,6 +1254,7 @@
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
+ /* translators: %s: Refuned count, %s: Refunded count. */
'label_count' => _n_noop( 'Refunded <span class="count">(%s)</span>', 'Refunded <span class="count">(%s)</span>', 'lifterlms' ),
),
'llms-txn-succeeded' => array(
--- a/lifterlms/includes/controllers/class.llms.controller.orders.php
+++ b/lifterlms/includes/controllers/class.llms.controller.orders.php
@@ -653,6 +653,7 @@
// Record order status changes as notes.
if ( 'order' === $post_type ) {
+ /* translators: %1$s: Old Status, %2$s: New status. */
$obj->add_note( sprintf( __( 'Order status changed from %1$s to %2$s', 'lifterlms' ), llms_get_order_status_name( $old_status ), llms_get_order_status_name( $new_status ) ) );
}
--- a/lifterlms/includes/elementor/class-llms-elementor-widget-base.php
+++ b/lifterlms/includes/elementor/class-llms-elementor-widget-base.php
@@ -21,7 +21,10 @@
array(
'label' => '',
'type' => ElementorControls_Manager::RAW_HTML,
- 'raw' => '<hr><p style="margin-top: 20px;">' . sprintf( esc_html__( 'Learn more about %1$sediting LifterLMS courses with Elementor%2$s', 'lifterlms' ), '<a target="_blank" href="https://lifterlms.com/docs/how-to-edit-courses-with-elementor/?utm_source=LifterLMS%20Plugin&utm_medium=Elementor%20Edit%20Panel%20&utm_campaign=Plugin%20to%20Sale">', '</a>' ) . '</p>',
+ 'raw' => '<hr><p style="margin-top: 20px;">' .
+ /* translators: %1$s: Opening learn more link tag, %2$s: Closing link tag. */
+ sprintf( esc_html__( 'Learn more about %1$sediting LifterLMS courses with Elementor%2$s', 'lifterlms' ), '<a target="_blank" href="https://lifterlms.com/docs/how-to-edit-courses-with-elementor/?utm_source=LifterLMS%20Plugin&utm_medium=Elementor%20Edit%20Panel%20&utm_campaign=Plugin%20to%20Sale">', '</a>' ) .
+ '</p>',
'content_classes' => 'lifterlms-notice',
)
);
--- a/lifterlms/includes/functions/llms-functions-deprecated.php
+++ b/lifterlms/includes/functions/llms-functions-deprecated.php
@@ -89,13 +89,12 @@
}
// query postmeta table and find all users enrolled
- $table_name = $wpdb->prefix . 'lifterlms_user_postmeta';
$meta_key_status = '_status';
$meta_value_status = 'Enrolled';
$results = $wpdb->get_results(
$wpdb->prepare(
- 'SELECT * FROM ' . $table_name . ' WHERE post_id = %d AND meta_key = "%s" AND meta_value = %s ORDER BY updated_date DESC',
+ "SELECT * FROM {$wpdb->prefix}lifterlms_user_postmeta WHERE post_id = %d AND meta_key = %s AND meta_value = %s ORDER BY updated_date DESC",
$post->ID,
$meta_key_status,
$meta_value_status
@@ -117,7 +116,7 @@
$start_date = $wpdb->get_results(
$wpdb->prepare(
- 'SELECT updated_date FROM ' . $table_name . ' WHERE user_id = %d AND post_id = %d AND meta_key = %s AND meta_value = %s ORDER BY updated_date DESC',
+ "SELECT updated_date FROM {$wpdb->prefix}lifterlms_user_postmeta WHERE user_id = %d AND post_id = %d AND meta_key = %s AND meta_value = %s ORDER BY updated_date DESC",
$user_id,
$post->ID,
$meta_key_start_date,
@@ -152,7 +151,7 @@
);
// change enrolled to expired in user_postmeta
- $wpdb->update( $table_name, $status_update, $set_user_expired );
+ $wpdb->update( $wpdb->prefix . 'lifterlms_user_postmeta', $status_update, $set_user_expired );
// remove membership id from usermeta array
$users_levels = get_user_meta( $user_id, '_llms_restricted_levels', true );
--- a/lifterlms/includes/functions/llms.functions.currency.php
+++ b/lifterlms/includes/functions/llms.functions.currency.php
@@ -30,7 +30,6 @@
* @param string $currency Currency code.
*/
return apply_filters( 'lifterlms_currency', get_option( 'lifterlms_currency', 'USD' ) );
-
}
/**
@@ -85,7 +84,6 @@
* @param array $currencies A list of currency codes to currency names. See "languages/currencies.php" for details.
*/
return apply_filters( 'lifterlms_currencies', $currencies );
-
}
/**
@@ -213,7 +211,6 @@
* @param array $symbols List of currency codes to their symbol. See "languages/currency-symbols.php" for details.
*/
return apply_filters( 'lifterlms_currency_symbols', $symbols );
-
}
/**
@@ -270,7 +267,7 @@
* @return string
*/
function llms_price_raw( $price, $args = array() ) {
- return html_entity_decode( strip_tags( llms_price( $price, $args ) ) );
+ return html_entity_decode( wp_strip_all_tags( llms_price( $price, $args ) ) );
}
/**
--- a/lifterlms/includes/functions/llms.functions.templates.dashboard.php
+++ b/lifterlms/includes/functions/llms.functions.templates.dashboard.php
@@ -1015,7 +1015,7 @@
*/
function lifterlms_template_student_dashboard_wrapper_open( $layout ) {
$current = LLMS_Student_Dashboard::get_current_tab( 'slug' );
- echo '<div class="llms-student-dashboard ' . $current . ' llms-sd-layout-' . esc_attr( $layout ) . '" data-current="' . $current . '">';
+ echo '<div class="llms-student-dashboard ' . esc_attr( $current ) . ' llms-sd-layout-' . esc_attr( $layout ) . '" data-current="' . esc_attr( $current ) . '">';
}
endif;
--- a/lifterlms/includes/integrations/class.llms.integration.bbpress.php
+++ b/lifterlms/includes/integrations/class.llms.integration.bbpress.php
@@ -80,7 +80,8 @@
}
public function set_title_and_description() {
- $this->title = __( 'bbPress', 'lifterlms' );
+ $this->title = __( 'bbPress', 'lifterlms' );
+ /* translators: %1$s: Open learn more link tag, %2$s: Closing tag. */
$this->description = sprintf( __( 'Restrict forums and topics to memberships, add forums to courses, and %1$smore%2$s.', 'lifterlms' ), '<a href="https://lifterlms.com/docs/lifterlms-and-bbpress/" target="_blank">', '</a>' );
}
--- a/lifterlms/includes/integrations/class.llms.integration.buddypress.php
+++ b/lifterlms/includes/integrations/class.llms.integration.buddypress.php
@@ -80,7 +80,8 @@
}
public function set_title_and_description() {
- $this->title = __( 'BuddyPress', 'lifterlms' );
+ $this->title = __( 'BuddyPress', 'lifterlms' );
+ /* translators: %1$s: Open learn more link tag, %2$s: Closing tag. */
$this->description = sprintf( __( 'Add LifterLMS information to user profiles and enable membership restrictions for activity, group, and member directories. %1$sLearn More%2$s.', 'lifterlms' ), '<a href="https://lifterlms.com/docs/lifterlms-and-buddypress/" target="_blank">', '</a>' );
}
--- a/lifterlms/includes/widgets/class.llms.widget.php
+++ b/lifterlms/includes/widgets/class.llms.widget.php
@@ -85,7 +85,7 @@
*/
public function update( $new_instance, $old_instance ) {
$instance = array();
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
+ $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? wp_strip_all_tags( $new_instance['title'] ) : '';
return $instance;
}
--- a/lifterlms/libraries/lifterlms-helper/class-lifterlms-helper.php
+++ b/lifterlms/libraries/lifterlms-helper/class-lifterlms-helper.php
@@ -24,7 +24,7 @@
*
* @var string
*/
- public $version = '3.5.7';
+ public $version = '3.5.8';
/**
* Singleton instance reference
--- a/lifterlms/libraries/lifterlms-helper/includes/views/beta-testing.php
+++ b/lifterlms/libraries/lifterlms-helper/includes/views/beta-testing.php
@@ -64,15 +64,15 @@
$addon = llms_get_add_on( $addon );
?>
<tr>
- <td><?php echo $addon->get( 'title' ); ?></td>
+ <td><?php echo esc_html( $addon->get( 'title' ) ); ?></td>
<td>
- <select name="llms_channel_subscriptions[<?php echo $addon->get( 'id' ); ?>]">
+ <select name="llms_channel_subscriptions[<?php echo esc_attr( $addon->get( 'id' ) ); ?>]">
<option value="stable" <?php selected( 'stable', $addon->get_channel_subscription() ); ?>><?php esc_html_e( 'Stable', 'lifterlms' ); ?></option>
<option value="beta" <?php selected( 'beta', $addon->get_channel_subscription() ); ?>><?php esc_html_e( 'Beta', 'lifterlms' ); ?></option>
</select>
</td>
- <td><?php echo $addon->get_installed_version(); ?></td>
- <td><?php echo $addon->get( 'version_beta' ) ? $addon->get( 'version_beta' ) : __( 'N/A', 'lifterlms' ); ?></td>
+ <td><?php echo esc_html( $addon->get_installed_version() ); ?></td>
+ <td><?php echo esc_html( $addon->get( 'version_beta' ) ? $addon->get( 'version_beta' ) : __( 'N/A', 'lifterlms' ) ); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
--- a/lifterlms/libraries/lifterlms-helper/lifterlms-helper.php
+++ b/lifterlms/libraries/lifterlms-helper/lifterlms-helper.php
@@ -10,7 +10,7 @@
* Plugin Name: LifterLMS Helper
* Plugin URI: https://lifterlms.com/
* Description: Update, install, and beta test LifterLMS and LifterLMS add-ons
- * Version: 3.5.7
+ * Version: 3.5.8
* Author: LifterLMS
* Author URI: https://lifterlms.com
* Text Domain: lifterlms
--- a/lifterlms/lifterlms.php
+++ b/lifterlms/lifterlms.php
@@ -10,7 +10,7 @@
* Plugin Name: LifterLMS
* Plugin URI: https://lifterlms.com/
* Description: Complete e-learning platform to sell online courses, protect lessons, offer memberships, and quiz students. WP Learning Management System.
- * Version: 9.2.1
+ * Version: 9.2.2
* Author: LifterLMS
* Author URI: https://lifterlms.com/
* Text Domain: lifterlms
--- a/lifterlms/templates/course/lesson-preview.php
+++ b/lifterlms/templates/course/lesson-preview.php
@@ -19,7 +19,7 @@
defined( 'ABSPATH' ) || exit;
$restrictions = llms_page_restricted( $lesson->get( 'id' ), get_current_user_id() );
-$data_msg = $restrictions['is_restricted'] ? ' data-tooltip-msg="' . esc_html( strip_tags( llms_get_restriction_message( $restrictions ) ) ) . '"' : '';
+$data_msg = $restrictions['is_restricted'] ? ' data-tooltip-msg="' . esc_html( wp_strip_all_tags( llms_get_restriction_message( $restrictions ) ) ) . '"' : '';
// Get the section name for this lesson.
$section = $lesson->get_parent_section() ? llms_get_post( $lesson->get_parent_section() ) : false;
@@ -46,7 +46,7 @@
<section
<?php if ( $restrictions['is_restricted'] ) : ?>
class="llms-lesson-locked"
- data-tooltip-msg="<?php echo esc_attr( strip_tags( llms_get_restriction_message( $restrictions ) ) ); ?>"
+ data-tooltip-msg="<?php echo esc_attr( wp_strip_all_tags( llms_get_restriction_message( $restrictions ) ) ); ?>"
<?php endif; ?>
>
<?php if ( $restrictions['is_restricted'] ) : ?>
@@ -73,7 +73,10 @@
<aside class="llms-extra">
<span class="llms-lesson-counter" aria-hidden="true">
- <?php echo esc_html( sprintf( _x( '%1$d of %2$d', 'lesson order within section', 'lifterlms' ), isset( $order ) ? $order : $lesson->get( 'order' ), $total_lessons ) ); ?>
+ <?php
+ // Translators: %1$d: Lesson number, %2$d: total number of lessons in section.
+ echo esc_html( sprintf( _x( '%1$d of %2$d', 'lesson order within section', 'lifterlms' ), isset( $order ) ? $order : $lesson->get( 'order' ), $total_lessons ) );
+ ?>
</span>
<?php echo wp_kses_post( $lesson->get_preview_icon_html() ); ?>
</aside>
@@ -104,7 +107,7 @@
<span class="screen-reader-text"><?php echo esc_attr( $lesson_screen_reader_msg ); ?></span>
<?php if ( $restrictions['is_restricted'] ) : ?>
- <span class="screen-reader-text"><?php echo esc_html( strip_tags( llms_get_restriction_message( $restrictions ) ) ); ?></span>
+ <span class="screen-reader-text"><?php echo esc_html( wp_strip_all_tags( llms_get_restriction_message( $restrictions ) ) ); ?></span>
<?php endif; ?>
</div>
--- a/lifterlms/templates/myaccount/my-grades-single-table.php
+++ b/lifterlms/templates/myaccount/my-grades-single-table.php
@@ -35,7 +35,7 @@
<td class="llms-lesson_title" colspan="2">
<?php echo wp_kses_post( sprintf( __( 'Lesson %1$d: %2$s', 'lifterlms' ), $lesson->get( 'order' ), $title ) ); ?>
<?php if ( $restricted['is_restricted'] ) : ?>
- <a data-tooltip-msg="<?php echo esc_attr( strip_tags( llms_get_restriction_message( $restricted ) ) ); ?>" href="#llms-lesson-locked">
+ <a data-tooltip-msg="<?php echo esc_attr( wp_strip_all_tags( llms_get_restriction_message( $restricted ) ) ); ?>" href="#llms-lesson-locked">
<i class="fa fa-lock" aria-hidden="true"></i>
</a>
<?php endif; ?>
--- a/lifterlms/templates/quiz/questions/content-choice.php
+++ b/lifterlms/templates/quiz/questions/content-choice.php
@@ -21,7 +21,7 @@
<fieldset class="llms-question-choices">
<legend class="sr-only">
<?php
- echo esc_html( strip_tags( $question->get_question( 'html', $attempt ) ) );
+ echo esc_html( wp_strip_all_tags( $question->get_question( 'html', $attempt ) ) );
?>
</legend>
<?php foreach ( $question->get_choices() as $choice ) : ?>
--- a/lifterlms/templates/quiz/questions/content-picture_choice.php
+++ b/lifterlms/templates/quiz/questions/content-picture_choice.php
@@ -24,7 +24,7 @@
<fieldset class="llms-question-choices type--picture">
<legend class="sr-only">
<?php
- echo esc_html( strip_tags( $question->get_question( 'html', $attempt ) ) );
+ echo esc_html( wp_strip_all_tags( $question->get_question( 'html', $attempt ) ) );
?>
</legend>
<?php foreach ( $choices as $choice ) : ?>
--- a/lifterlms/vendor/autoload.php
+++ b/lifterlms/vendor/autoload.php
@@ -3,8 +3,18 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
- echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
- exit(1);
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, $err);
+ } elseif (!headers_sent()) {
+ echo $err;
+ }
+ }
+ throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
--- a/lifterlms/vendor/composer/ClassLoader.php
+++ b/lifterlms/vendor/composer/ClassLoader.php
@@ -42,35 +42,37 @@
*/
class ClassLoader
{
- /** @var ?string */
+ /** @var Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
private $vendorDir;
// PSR-4
/**
- * @var array[]
- * @psalm-var array<string, array<string, int>>
+ * @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, array<int, string>>
+ * @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
- * @var array[]
- * @psalm-var array<string, array<string, string[]>>
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('FooBar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -78,8 +80,7 @@
private $useIncludePath = false;
/**
- * @var string[]
- * @psalm-var array<string, string>
+ * @var array<string, string>
*/
private $classMap = array();
@@ -87,29 +88,29 @@
private $classMapAuthoritative = false;
/**
- * @var bool[]
- * @psalm-var array<string, bool>
+ * @var array<string, bool>
*/
private $missingClasses = array();
- /** @var ?string */
+ /** @var string|null */
private $apcuPrefix;
/**
- * @var self[]
+ * @var array<string, self>
*/
private static $registeredLoaders = array();
/**
- * @param ?string $vendorDir
+ * @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
}
/**
- * @return string[]
+ * @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -121,8 +122,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, array<int, string>>
+ * @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -130,8 +130,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirs()
{
@@ -139,8 +138,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -148,8 +146,7 @@
}
/**
- * @return string[] Array of classname => path
- * @psalm-return array<string, string>
+ * @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -157,8 +154,7 @@
}
/**
- * @param string[] $classMap Class to filename map
- * @psalm-param array<string, string> $classMap
+ * @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -175,24 +171,25 @@
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
- (array) $paths
+ $paths
);
}
@@ -201,19 +198,19 @@
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+ $this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -222,9 +219,9 @@
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\'
- * @param string[]|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws InvalidArgumentException
*
@@ -232,17 +229,18 @@
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
- (array) $paths
+ $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -252,18 +250,18 @@
throw new InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -272,8 +270,8 @@
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 base directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -290,8 +288,8 @@
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\'
- * @param string[]|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\'
+ * @param list<string>|string $paths The PSR-4 base directories
*
* @throws InvalidArgumentException
*
@@ -425,7 +423,8 @@
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- includeFile($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
@@ -476,9 +475,9 @@
}
/**
- * Returns the currently registered loaders indexed by their corresponding vendor directories.
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
*
- * @return self[]
+ * @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -555,18 +554,26 @@
return false;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param string $file
- * @return void
- * @private
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
}
--- a/lifterlms/vendor/composer/InstalledVersions.php
+++ b/lifterlms/vendor/composer/InstalledVersions.php
@@ -27,12 +27,23 @@
class InstalledVersions
{
/**
+ * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
+ * @internal
+ */
+ private static $selfDir = null;
+
+ /**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
+ * @var bool
+ */
+ private static $installedIsLocalDir;
+
+ /**
* @var bool|null
*/
private static $canGetVendors;
@@ -98,7 +109,7 @@
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
- return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
@@ -119,7 +130,7 @@
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
- $constraint = $parser->parseConstraints($constraint);
+ $constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
@@ -309,6 +320,24 @@
{
self::$installed = $data;
self::$installedByVendor = array();
+
+ // when using reload, we disable the duplicate protection to ensure that self::$installed data is
+ // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
+ // so we have to assume it does not, and that may result in duplicate data being returned when listing
+ // all installed packages for example
+ self::$installedIsLocalDir = false;
+ }
+
+ /**
+ * @return string
+ */
+ private static function getSelfDir()
+ {
+ if (self::$selfDir === null) {
+ self::$selfDir = strtr(__DIR__, '\', '/');
+ }
+
+ return self::$selfDir;
}
/**
@@ -322,17 +351,27 @@
}
$installed = array();
+ $copiedLocalDir = false;
if (self::$canGetVendors) {
+ $selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ $vendorDir = strtr($vendorDir, '\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installe