Paid Memberships Pro - Version 2.6.7

Version Description

  • 2022-01-06 =
  • SECURITY: Updated escaping in the pmpro_getLevelAtCheckout and pmpro_checkDiscountCode functions as extra precaution against SQL injections. (Thanks, WPScan)
Download this release

Release Info

Developer strangerstudios
Plugin Icon 128x128 Paid Memberships Pro
Version 2.6.7
Comparing to
See all releases

Code changes from version 2.6.6 to 2.6.7

CHANGELOG.txt CHANGED
@@ -1,4 +1,7 @@
1
  == Changelog ==
 
 
 
2
  = 2.6.6 - 2021-11-18 =
3
  * SECURITY: Updated escaping on the discount codes page in the dashboard to prevent XSS attacks. #1867 (Thanks, Erwan from WPScan)
4
  * BUG FIX/ENHANCEMENT: Added code to remove duplicate active rows in the pmpro_memberships_users table after level change. This might have happened e.g. if users were purchasing a level via the WooCommerce Add On multiple times. #1860 (@dlparker1005)
1
  == Changelog ==
2
+ = 2.6.7 - 2022-01-06 =
3
+ * SECURITY: Updated escaping in the pmpro_getLevelAtCheckout and pmpro_checkDiscountCode functions as extra precaution against SQL injections. (Thanks, WPScan)
4
+
5
  = 2.6.6 - 2021-11-18 =
6
  * SECURITY: Updated escaping on the discount codes page in the dashboard to prevent XSS attacks. #1867 (Thanks, Erwan from WPScan)
7
  * BUG FIX/ENHANCEMENT: Added code to remove duplicate active rows in the pmpro_memberships_users table after level change. This might have happened e.g. if users were purchasing a level via the WooCommerce Add On multiple times. #1860 (@dlparker1005)
includes/functions.php CHANGED
@@ -110,7 +110,7 @@ function pmpro_get_slug( $post_id ) {
110
  $post_id = intval( $post_id );
111
 
112
  if ( ! $pmpro_slugs[ $post_id ] ) {
113
- $pmpro_slugs[ $post_id ] = $wpdb->get_var( "SELECT post_name FROM $wpdb->posts WHERE ID = '" . $post_id . "' LIMIT 1" );
114
  }
115
 
116
  return $pmpro_slugs[ $post_id ];
@@ -1079,7 +1079,7 @@ function pmpro_changeMembershipLevel( $level, $user_id = null, $old_level_status
1079
  if ( $old_levels && $pmpro_deactivate_old_levels ) {
1080
  foreach ( $old_levels as $old_level ) {
1081
 
1082
- $sql = "UPDATE $wpdb->pmpro_memberships_users SET `status`='$old_level_status', `enddate`='" . current_time( 'mysql' ) . "' WHERE `id`=" . $old_level->subscription_id;
1083
 
1084
  if ( ! $wpdb->query( $sql ) ) {
1085
  $pmpro_error = __( 'Error interacting with database', 'paid-memberships-pro' ) . ': ' . ( $wpdb->last_error ? $wpdb->last_error : 'unavailable' );
@@ -1093,7 +1093,7 @@ function pmpro_changeMembershipLevel( $level, $user_id = null, $old_level_status
1093
  if ( ! empty( $cancel_level ) ) {
1094
  $pmpro_cancel_previous_subscriptions = true; // don't filter cause we're doing just the one
1095
 
1096
- $other_order_ids = $wpdb->get_col( "SELECT id FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $user_id . "' AND status = 'success' AND membership_id = '" . esc_sql( $cancel_level ) . "' ORDER BY id DESC LIMIT 1" );
1097
  } else {
1098
  $pmpro_cancel_previous_subscriptions = true;
1099
  if ( isset( $_REQUEST['cancel_membership'] ) && $_REQUEST['cancel_membership'] == false ) {
@@ -1104,7 +1104,7 @@ function pmpro_changeMembershipLevel( $level, $user_id = null, $old_level_status
1104
  $other_order_ids = $wpdb->get_col(
1105
  "SELECT id, IF(subscription_transaction_id = '', CONCAT('UNIQUE_SUB_ID_', id), subscription_transaction_id) as unique_sub_id
1106
  FROM $wpdb->pmpro_membership_orders
1107
- WHERE user_id = '" . $user_id . "'
1108
  AND status = 'success'
1109
  GROUP BY unique_sub_id
1110
  ORDER BY id DESC"
@@ -1409,7 +1409,7 @@ function pmpro_getMembershipCategories( $level_id ) {
1409
  $categories = $wpdb->get_col(
1410
  "SELECT c.category_id
1411
  FROM {$wpdb->pmpro_memberships_categories} AS c
1412
- WHERE c.membership_id = '" . $level_id . "'"
1413
  );
1414
 
1415
  return $categories;
@@ -1788,7 +1788,7 @@ function pmpro_checkDiscountCode( $code, $level_id = null, $return_errors = fals
1788
  // have we run out of uses?
1789
  if ( ! $error ) {
1790
  if ( $dbcode->uses > 0 ) {
1791
- $used = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . $dbcode->id . "'" );
1792
  if ( $used >= $dbcode->uses ) {
1793
  $error = __( 'This discount code is no longer valid.', 'paid-memberships-pro' );
1794
  }
@@ -1806,7 +1806,7 @@ function pmpro_checkDiscountCode( $code, $level_id = null, $return_errors = fals
1806
  } else {
1807
  $level_id = intval( $level_id );
1808
  }
1809
- $code_level = $wpdb->get_row( "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id WHERE cl.code_id = '" . $dbcode->id . "' AND cl.level_id IN (" . $level_id . ") LIMIT 1" );
1810
 
1811
  if ( empty( $code_level ) ) {
1812
  $error = __( 'This discount code does not apply to this membership level.', 'paid-memberships-pro' );
@@ -2205,7 +2205,7 @@ function pmpro_getLevel( $level ) {
2205
  return $pmpro_levels[ $level_id ];
2206
  } else {
2207
  global $wpdb;
2208
- $pmpro_levels[ $level_id ] = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1" );
2209
  }
2210
  } else {
2211
  global $wpdb;
@@ -2356,7 +2356,7 @@ function pmpro_getLevelAtCheckout( $level_id = null, $discount_code = null ) {
2356
 
2357
  // what level are they purchasing? (discount code passed)
2358
  if ( ! empty( $level_id ) && ! empty( $discount_code ) ) {
2359
- $discount_code_id = $wpdb->get_var( "SELECT id FROM $wpdb->pmpro_discount_codes WHERE code = '" . $discount_code . "' LIMIT 1" );
2360
 
2361
  // check code
2362
  global $pmpro_checkout_level_ids; // Set by MMPU.
@@ -2366,12 +2366,12 @@ function pmpro_getLevelAtCheckout( $level_id = null, $discount_code = null ) {
2366
  $code_check = pmpro_checkDiscountCode( $discount_code, $level_id, true );
2367
  }
2368
  if ( $code_check[0] != false ) {
2369
- $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups, l.confirmation FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . $level_id . "' LIMIT 1";
2370
  $pmpro_level = $wpdb->get_row( $sqlQuery );
2371
 
2372
  // if the discount code doesn't adjust the level, let's just get the straight level
2373
  if ( empty( $pmpro_level ) ) {
2374
- $pmpro_level = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1" );
2375
  }
2376
 
2377
  // filter adjustments to the level
@@ -2532,7 +2532,7 @@ if ( ! function_exists( 'pmpro_getMemberStartdate' ) ) {
2532
  if ( ! empty( $level_id ) ) {
2533
  $sqlQuery = "SELECT UNIX_TIMESTAMP(CONVERT_TZ(startdate, '+00:00', @@global.time_zone)) FROM $wpdb->pmpro_memberships_users WHERE status = 'active' AND membership_id IN(" . esc_sql( $level_id ) . ") AND user_id = '" . $user_id . "' ORDER BY id LIMIT 1";
2534
  } else {
2535
- $sqlQuery = "SELECT UNIX_TIMESTAMP(CONVERT_TZ(startdate, '+00:00', @@global.time_zone)) FROM $wpdb->pmpro_memberships_users WHERE status = 'active' AND user_id = '" . $user_id . "' ORDER BY id LIMIT 1";
2536
  }
2537
 
2538
  $startdate = apply_filters( 'pmpro_member_startdate', $wpdb->get_var( $sqlQuery ), $user_id, $level_id );
110
  $post_id = intval( $post_id );
111
 
112
  if ( ! $pmpro_slugs[ $post_id ] ) {
113
+ $pmpro_slugs[ $post_id ] = $wpdb->get_var( "SELECT post_name FROM $wpdb->posts WHERE ID = '" . esc_sql( $post_id ) . "' LIMIT 1" );
114
  }
115
 
116
  return $pmpro_slugs[ $post_id ];
1079
  if ( $old_levels && $pmpro_deactivate_old_levels ) {
1080
  foreach ( $old_levels as $old_level ) {
1081
 
1082
+ $sql = "UPDATE $wpdb->pmpro_memberships_users SET `status`='$old_level_status', `enddate`='" . esc_sql( current_time( 'mysql' ) ) . "' WHERE `id`=" . esc_sql( $old_level->subscription_id );
1083
 
1084
  if ( ! $wpdb->query( $sql ) ) {
1085
  $pmpro_error = __( 'Error interacting with database', 'paid-memberships-pro' ) . ': ' . ( $wpdb->last_error ? $wpdb->last_error : 'unavailable' );
1093
  if ( ! empty( $cancel_level ) ) {
1094
  $pmpro_cancel_previous_subscriptions = true; // don't filter cause we're doing just the one
1095
 
1096
+ $other_order_ids = $wpdb->get_col( "SELECT id FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . esc_sql( $user_id ) . "' AND status = 'success' AND membership_id = '" . esc_sql( $cancel_level ) . "' ORDER BY id DESC LIMIT 1" );
1097
  } else {
1098
  $pmpro_cancel_previous_subscriptions = true;
1099
  if ( isset( $_REQUEST['cancel_membership'] ) && $_REQUEST['cancel_membership'] == false ) {
1104
  $other_order_ids = $wpdb->get_col(
1105
  "SELECT id, IF(subscription_transaction_id = '', CONCAT('UNIQUE_SUB_ID_', id), subscription_transaction_id) as unique_sub_id
1106
  FROM $wpdb->pmpro_membership_orders
1107
+ WHERE user_id = '" . esc_sql( $user_id ) . "'
1108
  AND status = 'success'
1109
  GROUP BY unique_sub_id
1110
  ORDER BY id DESC"
1409
  $categories = $wpdb->get_col(
1410
  "SELECT c.category_id
1411
  FROM {$wpdb->pmpro_memberships_categories} AS c
1412
+ WHERE c.membership_id = '" . esc_sql( $level_id ) . "'"
1413
  );
1414
 
1415
  return $categories;
1788
  // have we run out of uses?
1789
  if ( ! $error ) {
1790
  if ( $dbcode->uses > 0 ) {
1791
+ $used = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . esc_sql( $dbcode->id ) . "'" );
1792
  if ( $used >= $dbcode->uses ) {
1793
  $error = __( 'This discount code is no longer valid.', 'paid-memberships-pro' );
1794
  }
1806
  } else {
1807
  $level_id = intval( $level_id );
1808
  }
1809
+ $code_level = $wpdb->get_row( "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id WHERE cl.code_id = '" . esc_sql( $dbcode->id ) . "' AND cl.level_id IN (" . esc_sql( $level_id ) . ") LIMIT 1" );
1810
 
1811
  if ( empty( $code_level ) ) {
1812
  $error = __( 'This discount code does not apply to this membership level.', 'paid-memberships-pro' );
2205
  return $pmpro_levels[ $level_id ];
2206
  } else {
2207
  global $wpdb;
2208
+ $pmpro_levels[ $level_id ] = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql( $level_id ) . "' LIMIT 1" );
2209
  }
2210
  } else {
2211
  global $wpdb;
2356
 
2357
  // what level are they purchasing? (discount code passed)
2358
  if ( ! empty( $level_id ) && ! empty( $discount_code ) ) {
2359
+ $discount_code_id = $wpdb->get_var( "SELECT id FROM $wpdb->pmpro_discount_codes WHERE code = '" . esc_sql( $discount_code ) . "' LIMIT 1" );
2360
 
2361
  // check code
2362
  global $pmpro_checkout_level_ids; // Set by MMPU.
2366
  $code_check = pmpro_checkDiscountCode( $discount_code, $level_id, true );
2367
  }
2368
  if ( $code_check[0] != false ) {
2369
+ $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups, l.confirmation FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . esc_sql( $discount_code ) . "' AND cl.level_id = '" . esc_sql( $level_id ) . "' LIMIT 1";
2370
  $pmpro_level = $wpdb->get_row( $sqlQuery );
2371
 
2372
  // if the discount code doesn't adjust the level, let's just get the straight level
2373
  if ( empty( $pmpro_level ) ) {
2374
+ $pmpro_level = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql( $level_id ) . "' LIMIT 1" );
2375
  }
2376
 
2377
  // filter adjustments to the level
2532
  if ( ! empty( $level_id ) ) {
2533
  $sqlQuery = "SELECT UNIX_TIMESTAMP(CONVERT_TZ(startdate, '+00:00', @@global.time_zone)) FROM $wpdb->pmpro_memberships_users WHERE status = 'active' AND membership_id IN(" . esc_sql( $level_id ) . ") AND user_id = '" . $user_id . "' ORDER BY id LIMIT 1";
2534
  } else {
2535
+ $sqlQuery = "SELECT UNIX_TIMESTAMP(CONVERT_TZ(startdate, '+00:00', @@global.time_zone)) FROM $wpdb->pmpro_memberships_users WHERE status = 'active' AND user_id = '" . esc_sql( $user_id ) . "' ORDER BY id LIMIT 1";
2536
  }
2537
 
2538
  $startdate = apply_filters( 'pmpro_member_startdate', $wpdb->get_var( $sqlQuery ), $user_id, $level_id );
paid-memberships-pro.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Paid Memberships Pro
4
  * Plugin URI: https://www.paidmembershipspro.com
5
  * Description: The most complete member management and membership subscriptions plugin for WordPress.
6
- * Version: 2.6.6
7
  * Author: Stranger Studios
8
  * Author URI: https://www.strangerstudios.com
9
  * Text Domain: paid-memberships-pro
@@ -16,7 +16,7 @@
16
  */
17
 
18
  // version constant
19
- define( 'PMPRO_VERSION', '2.6.6' );
20
  define( 'PMPRO_USER_AGENT', 'Paid Memberships Pro v' . PMPRO_VERSION . '; ' . site_url() );
21
  define( 'PMPRO_MIN_PHP_VERSION', '5.6' );
22
 
3
  * Plugin Name: Paid Memberships Pro
4
  * Plugin URI: https://www.paidmembershipspro.com
5
  * Description: The most complete member management and membership subscriptions plugin for WordPress.
6
+ * Version: 2.6.7
7
  * Author: Stranger Studios
8
  * Author URI: https://www.strangerstudios.com
9
  * Text Domain: paid-memberships-pro
16
  */
17
 
18
  // version constant
19
+ define( 'PMPRO_VERSION', '2.6.7' );
20
  define( 'PMPRO_USER_AGENT', 'Paid Memberships Pro v' . PMPRO_VERSION . '; ' . site_url() );
21
  define( 'PMPRO_MIN_PHP_VERSION', '5.6' );
22
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: memberships, members, subscriptions, ecommerce, user registration, member,
4
  Requires at least: 5.2
5
  Tested up to: 5.8.1
6
  Requires PHP: 5.6
7
- Stable tag: 2.6.6
8
 
9
  Get Paid with Paid Memberships Pro: The most complete member management and membership subscriptions plugin for your WordPress site.
10
 
@@ -156,6 +156,9 @@ Not sure? You can find out by doing a bit a research.
156
  9. Membership Account page, display all sections or show specific sections using shortcode attributes.
157
 
158
  == Changelog ==
 
 
 
159
  = 2.6.6 - 2021-11-18 =
160
  * SECURITY: Updated escaping on the discount codes page in the dashboard to prevent XSS attacks. #1867 (Thanks, Erwan from WPScan)
161
  * BUG FIX/ENHANCEMENT: Added code to remove duplicate active rows in the pmpro_memberships_users table after level change. This might have happened e.g. if users were purchasing a level via the WooCommerce Add On multiple times. #1860 (@dlparker1005)
4
  Requires at least: 5.2
5
  Tested up to: 5.8.1
6
  Requires PHP: 5.6
7
+ Stable tag: 2.6.7
8
 
9
  Get Paid with Paid Memberships Pro: The most complete member management and membership subscriptions plugin for your WordPress site.
10
 
156
  9. Membership Account page, display all sections or show specific sections using shortcode attributes.
157
 
158
  == Changelog ==
159
+ = 2.6.7 - 2022-01-06 =
160
+ * SECURITY: Updated escaping in the pmpro_getLevelAtCheckout and pmpro_checkDiscountCode functions as extra precaution against SQL injections. (Thanks, WPScan)
161
+
162
  = 2.6.6 - 2021-11-18 =
163
  * SECURITY: Updated escaping on the discount codes page in the dashboard to prevent XSS attacks. #1867 (Thanks, Erwan from WPScan)
164
  * BUG FIX/ENHANCEMENT: Added code to remove duplicate active rows in the pmpro_memberships_users table after level change. This might have happened e.g. if users were purchasing a level via the WooCommerce Add On multiple times. #1860 (@dlparker1005)