| @@ -219,8 +219,16 @@ | ||
| 219 | 219 | if ( strpos( $_image_url, $content_url ) !== 0 ) { |
| 220 | 220 | return new WP_Error( 'invalid_image', __( 'Invalid image url.', 'userswp' ) ); |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | + // Only allow cropping the image the current user just uploaded (normalized like $image_url). | |
| 224 | + $pending_key = '_uwp_pending_' . $type . '_upload'; | |
| 225 | + $pending_url = get_user_meta( get_current_user_id(), $pending_key, true ); | |
| 226 | + $pending_url = $pending_url ? str_replace( array( 'https://', 'http://' ), '', $this->normalize_url( esc_url( $pending_url ) ) ) : ''; | |
| 227 | + if ( empty( $pending_url ) || $pending_url !== $_image_url ) { | |
| 228 | + return new WP_Error( 'crop_session_expired', __( 'Your image upload could not be verified. Please upload the image again.', 'userswp' ) ); | |
| 229 | + } | |
| 230 | + | |
| 223 | 231 | $filetype = wp_check_filetype( $image_url ); |
| 224 | 232 | |
| 225 | 233 | if ( empty( $filetype['ext'] ) ) { |
| 226 | 234 | return new WP_Error( 'invalid_image', __( 'Invalid image type.', 'userswp' ) ); |
| @@ -281,8 +289,15 @@ | ||
| 281 | 289 | wp_die( esc_html__( 'Something went wrong. Please contact site admin.', 'userswp' ), 403 ); |
| 282 | 290 | } |
| 283 | 291 | |
| 284 | 292 | $cropped = uwp_resizeThumbnailImage( $thumb_image_location, $image_path, $x, $y, $w, $h, $scale ); |
| 293 | + | |
| 294 | + // Resize returns a path even on failure; bail before touching meta or files so the crop can be retried. | |
| 295 | + clearstatcache( true, $thumb_image_location ); | |
| 296 | + if ( ! is_file( $thumb_image_location ) ) { | |
| 297 | + return new WP_Error( 'crop_failed', __( 'Could not crop the image. Please try again.', 'userswp' ) ); | |
| 298 | + } | |
| 299 | + | |
| 285 | 300 | $cropped = str_replace( $upload_path, $upload_url, $cropped ); |
| 286 | 301 | |
| 287 | 302 | // Remove previous avatar/banner |
| 288 | 303 | $unlink_img = ''; |
| @@ -297,13 +312,34 @@ | ||
| 297 | 312 | } else { |
| 298 | 313 | uwp_update_usermeta( $user_id, 'banner_thumb', $cropped ); |
| 299 | 314 | } |
| 300 | 315 | |
| 301 | - if ( $unlink_img && $unlink_img != $thumb_image_location && is_file( $unlink_img ) && file_exists( $unlink_img ) ) { | |
| 302 | - @unlink( $unlink_img ); | |
| 303 | - $unlink_ori_img = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $unlink_img ); | |
| 304 | - if ( is_file( $unlink_ori_img ) && file_exists( $unlink_ori_img ) ) { | |
| 305 | - @unlink( $unlink_ori_img ); | |
| 316 | + $original_key = '_uwp_' . $type . '_original'; | |
| 317 | + $prev_original = get_user_meta( $user_id, $original_key, true ); | |
| 318 | + | |
| 319 | + delete_user_meta( get_current_user_id(), $pending_key ); | |
| 320 | + $relative_original = ltrim( wp_normalize_path( str_replace( wp_normalize_path( untrailingslashit( $upload_path ) ), '', wp_normalize_path( $image_path ) ) ), '/' ); | |
| 321 | + update_user_meta( $user_id, $original_key, $relative_original ); | |
| 322 | + | |
| 323 | + // Enforce containment inside uploads before deleting, matching upload_file_remove(). | |
| 324 | + $real_upload_path = realpath( $upload_path ); | |
| 325 | + $real_unlink_img = $unlink_img ? realpath( $unlink_img ) : false; | |
| 326 | + | |
| 327 | + if ( $real_upload_path && $real_unlink_img && realpath( $thumb_image_location ) !== $real_unlink_img | |
| 328 | + && false !== strpos( basename( $real_unlink_img ), $thumb_postfix . '.' ) | |
| 329 | + && 0 === strpos( $real_unlink_img, $real_upload_path . DIRECTORY_SEPARATOR ) | |
| 330 | + && is_file( $real_unlink_img ) ) { | |
| 331 | + wp_delete_file( $real_unlink_img ); | |
| 332 | + | |
| 333 | + // Delete the previous source only if it is the exact file this user cropped. | |
| 334 | + $unlink_ori_img = str_replace( $thumb_postfix . '.', '.', $real_unlink_img ); | |
| 335 | + $real_unlink_ori_img = realpath( $unlink_ori_img ); | |
| 336 | + $expected_original = $prev_original ? realpath( untrailingslashit( $upload_path ) . '/' . $prev_original ) : false; | |
| 337 | + if ( $expected_original && $real_unlink_ori_img && $expected_original === $real_unlink_ori_img | |
| 338 | + && realpath( $image_path ) !== $real_unlink_ori_img | |
| 339 | + && 0 === strpos( $real_unlink_ori_img, $real_upload_path . DIRECTORY_SEPARATOR ) | |
| 340 | + && is_file( $real_unlink_ori_img ) ) { | |
| 341 | + wp_delete_file( $real_unlink_ori_img ); | |
| 306 | 342 | } |
| 307 | 343 | } |
| 308 | 344 | } |
| 309 | 345 | |
| @@ -360,22 +396,20 @@ | ||
| 360 | 396 | if ( ! is_user_logged_in() ) { |
| 361 | 397 | return false; |
| 362 | 398 | } |
| 363 | 399 | |
| 364 | - if ( empty( $_POST['uwp_reset_nonce'] ) || ! wp_verify_nonce( $_POST['uwp_reset_nonce'], 'uwp_reset_nonce_' . $type ) ) { | |
| 365 | - return; | |
| 366 | - } | |
| 367 | - | |
| 368 | 400 | if ( is_admin() && defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) { |
| 369 | 401 | $user_id = get_current_user_id(); |
| 370 | - // If is another user's profile page | |
| 371 | - } elseif ( is_admin() && ! empty( $_GET['user_id'] ) && is_numeric( $_GET['user_id'] ) ) { | |
| 402 | + } elseif ( is_admin() && current_user_can( 'manage_options' ) && ! empty( $_GET['user_id'] ) && is_numeric( $_GET['user_id'] ) ) { | |
| 372 | 403 | $user_id = absint( $_GET['user_id'] ); |
| 373 | - // Otherwise something is wrong. | |
| 374 | 404 | } else { |
| 375 | 405 | $user_id = get_current_user_id(); |
| 376 | 406 | } |
| 377 | 407 | |
| 408 | + if ( empty( $_POST['uwp_reset_nonce'] ) || ! wp_verify_nonce( $_POST['uwp_reset_nonce'], 'uwp_reset_nonce_' . $type . '_' . $user_id ) ) { | |
| 409 | + return; | |
| 410 | + } | |
| 411 | + | |
| 378 | 412 | $errors = new WP_Error(); |
| 379 | 413 | if ( empty( $user_id ) ) { |
| 380 | 414 | $errors->add( 'something_wrong', __( 'Something went wrong. Please try again.', 'userswp' ) ); |
| 381 | 415 | } |
| @@ -392,8 +426,13 @@ | ||
| 392 | 426 | } else { |
| 393 | 427 | // Do nothing |
| 394 | 428 | } |
| 395 | 429 | |
| 430 | + if ( in_array( $type, array( 'avatar', 'banner' ), true ) ) { | |
| 431 | + delete_user_meta( $user_id, '_uwp_' . $type . '_original' ); | |
| 432 | + delete_user_meta( get_current_user_id(), '_uwp_pending_' . $type . '_upload' ); | |
| 433 | + } | |
| 434 | + | |
| 396 | 435 | if ( is_admin() ) { |
| 397 | 436 | if ( $user_id == get_current_user_id() ) { |
| 398 | 437 | $redirect_url = admin_url( 'profile.php' ); |
| 399 | 438 | } else { |
| @@ -1177,8 +1216,11 @@ | ||
| 1177 | 1216 | global $wp2fa; |
| 1178 | 1217 | if ( wp_doing_ajax() && isset( $wp2fa ) && ! empty( $wp2fa ) ) { |
| 1179 | 1218 | remove_action( 'wp_login', array( $wp2fa->login, 'wp_login' ), 20 ); |
| 1180 | 1219 | } |
| 1220 | + if ( wp_doing_ajax() && class_exists( '\WP2FA\Authenticator\Login' ) ) { | |
| 1221 | + remove_action( 'wp_login', array( 'WP2FA\Authenticator\Login', 'wp_login' ), 20 ); | |
| 1222 | + } | |
| 1181 | 1223 | |
| 1182 | 1224 | $user = wp_signon( |
| 1183 | 1225 | array( |
| 1184 | 1226 | 'user_login' => $result['username'], |
| @@ -1187,10 +1229,14 @@ | ||
| 1187 | 1229 | ) |
| 1188 | 1230 | ); |
| 1189 | 1231 | |
| 1190 | 1232 | add_action( 'authenticate', 'gglcptch_login_check', 21, 1 ); |
| 1233 | + if ( wp_doing_ajax() && class_exists( '\WP2FA\Authenticator\Login' ) ) { | |
| 1234 | + add_action( 'wp_login', array( 'WP2FA\Authenticator\Login', 'wp_login' ), 20, 2 ); | |
| 1235 | + } | |
| 1191 | 1236 | |
| 1192 | - if ( wp_doing_ajax() && ! is_wp_error( $user ) && isset( $wp2fa ) && ! empty( $wp2fa ) ) { | |
| 1237 | + $wp2fa_available = ( isset( $wp2fa ) && ! empty( $wp2fa ) ) || class_exists( '\WP2FA\Authenticator\Login' ); | |
| 1238 | + if ( wp_doing_ajax() && ! is_wp_error( $user ) && $wp2fa_available ) { | |
| 1193 | 1239 | |
| 1194 | 1240 | $two_fa = $this->check_2fa( $user ); |
| 1195 | 1241 | if ( isset( $two_fa ) && ! empty( $two_fa ) ) { |
| 1196 | 1242 | if ( is_wp_error( $two_fa ) ) { |
| @@ -1211,8 +1257,20 @@ | ||
| 1211 | 1257 | } |
| 1212 | 1258 | } |
| 1213 | 1259 | } |
| 1214 | 1260 | |
| 1261 | + if ( wp_doing_ajax() && is_wp_error( $user ) && $this->wordfence_2fa_available() ) { | |
| 1262 | + $wfls_2fa = $this->check_wordfence_2fa( $user, $result ); | |
| 1263 | + if ( ! empty( $wfls_2fa ) ) { | |
| 1264 | + wp_send_json_success( | |
| 1265 | + array( | |
| 1266 | + 'html' => $wfls_2fa, | |
| 1267 | + 'is_2fa' => true, | |
| 1268 | + ) | |
| 1269 | + ); | |
| 1270 | + } | |
| 1271 | + } | |
| 1272 | + | |
| 1215 | 1273 | if ( is_wp_error( $user ) ) { |
| 1216 | 1274 | $message = aui()->alert( |
| 1217 | 1275 | array( |
| 1218 | 1276 | 'type' => 'error', |
| @@ -1280,9 +1338,12 @@ | ||
| 1280 | 1338 | |
| 1281 | 1339 | return $errors; |
| 1282 | 1340 | } |
| 1283 | 1341 | |
| 1284 | - $provider = \WP2FA\Authenticator\Login::get_available_providers_for_user( $user ); | |
| 1342 | + $provider = $this->get_wp2fa_provider_for_user( $user ); | |
| 1343 | + if ( empty( $provider ) ) { | |
| 1344 | + return; | |
| 1345 | + } | |
| 1285 | 1346 | |
| 1286 | 1347 | ob_start(); |
| 1287 | 1348 | ?> |
| 1288 | 1349 | |
| @@ -1333,9 +1394,9 @@ | ||
| 1333 | 1394 | echo aui()->input( |
| 1334 | 1395 | array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 1335 | 1396 | 'type' => 'tel', |
| 1336 | 1397 | 'id' => 'authcode', |
| 1337 | - 'name' => 'wp-2fa-email-code', | |
| 1398 | + 'name' => 'authcode', | |
| 1338 | 1399 | 'placeholder' => esc_attr__( 'Verification Code', 'userswp' ), |
| 1339 | 1400 | 'value' => '', |
| 1340 | 1401 | 'label' => esc_html__( 'Verification Code', 'userswp' ), |
| 1341 | 1402 | 'extra_attributes' => array( |
| @@ -1370,9 +1431,9 @@ | ||
| 1370 | 1431 | </form> |
| 1371 | 1432 | </div> |
| 1372 | 1433 | |
| 1373 | 1434 | <?php |
| 1374 | - $codes_remaining = \WP2FA\Authenticator\Backup_Codes::codes_remaining_for_user( $user ); | |
| 1435 | + $codes_remaining = $this->get_wp2fa_backup_codes_remaining( $user ); | |
| 1375 | 1436 | if ( isset( $codes_remaining ) && $codes_remaining > 0 ) { |
| 1376 | 1437 | ?> |
| 1377 | 1438 | <div class="uwp-2fa-methods-wrap" style="display:none;"> |
| 1378 | 1439 | <form name="validate_2fa_backup_codes_form" id="validate_2fa_backup_codes_form" |
| @@ -1428,9 +1489,247 @@ | ||
| 1428 | 1489 | |
| 1429 | 1490 | return ob_get_clean(); |
| 1430 | 1491 | } |
| 1431 | 1492 | |
| 1493 | + /** | |
| 1494 | + * Checks if the Wordfence Login Security module (2FA) is available. | |
| 1495 | + * | |
| 1496 | + * @since 1.2.5 | |
| 1497 | + * @package userswp | |
| 1498 | + * | |
| 1499 | + * @return bool | |
| 1500 | + */ | |
| 1501 | + public function wordfence_2fa_available() { | |
| 1502 | + return class_exists( '\WordfenceLS\Controller_Users' ) && class_exists( '\WordfenceLS\Controller_TOTP' ); | |
| 1503 | + } | |
| 1504 | + | |
| 1505 | + /** | |
| 1506 | + * Checks whether Wordfence's 2FA requires a verification code for the | |
| 1507 | + * failed login attempt and, if so, returns the markup for the code entry form. | |
| 1508 | + * | |
| 1509 | + * @since 1.2.5 | |
| 1510 | + * @package userswp | |
| 1511 | + * | |
| 1512 | + * @param WP_Error $error The error returned by wp_signon(). | |
| 1513 | + * @param array $result The validated login fields (username/password). | |
| 1514 | + * | |
| 1515 | + * @return string|void The 2FA form markup, or nothing if not applicable. | |
| 1516 | + */ | |
| 1517 | + public function check_wordfence_2fa( $error, $result ) { | |
| 1518 | + if ( 1 == uwp_get_option( 'disable_wordfence_2fa' ) ) { | |
| 1519 | + return; | |
| 1520 | + } | |
| 1521 | + | |
| 1522 | + if ( ! $this->wordfence_2fa_available() ) { | |
| 1523 | + return; | |
| 1524 | + } | |
| 1525 | + | |
| 1526 | + if ( ! is_wp_error( $error ) || 'wfls_twofactor_required' !== $error->get_error_code() ) { | |
| 1527 | + return; | |
| 1528 | + } | |
| 1529 | + | |
| 1530 | + $username = ! empty( $result['username'] ) ? $result['username'] : ''; | |
| 1531 | + if ( empty( $username ) ) { | |
| 1532 | + return; | |
| 1533 | + } | |
| 1534 | + | |
| 1535 | + $user = is_email( $username ) ? get_user_by( 'email', $username ) : get_user_by( 'login', $username ); | |
| 1536 | + if ( ! $user ) { | |
| 1537 | + return; | |
| 1538 | + } | |
| 1539 | + | |
| 1540 | + if ( ! \WordfenceLS\Controller_Users::shared()->has_2fa_active( $user ) ) { | |
| 1541 | + return; | |
| 1542 | + } | |
| 1543 | + | |
| 1544 | + if ( \WordfenceLS\Controller_Users::shared()->has_remembered_2fa( $user ) ) { | |
| 1545 | + return; | |
| 1546 | + } | |
| 1547 | + | |
| 1548 | + $login_nonce = wp_create_nonce( 'uwp-wfls-2fa-' . $user->ID ); | |
| 1549 | + | |
| 1550 | + ob_start(); | |
| 1551 | + ?> | |
| 1552 | + | |
| 1553 | + <div class="uwp-2fa-methods-wrap"> | |
| 1554 | + <form name="validate_2fa_form" id="validate_2fa_form" class="validate_2fa_form" action="" method="post" | |
| 1555 | + autocomplete="off"> | |
| 1556 | + <input type="hidden" name="provider" id="provider" value="wordfence"/> | |
| 1557 | + <input type="hidden" name="uwp-auth-id" id="uwp-auth-id" value="<?php echo esc_attr( $user->ID ); ?>"/> | |
| 1558 | + <input type="hidden" name="wp-auth-nonce" id="wp-auth-nonce" | |
| 1559 | + value="<?php echo esc_attr( $login_nonce ); ?>"/> | |
| 1560 | + | |
| 1561 | + <p><?php esc_html_e( 'Please enter the authentication code from your two-factor authentication app, or a recovery code, to login:', 'userswp' ); ?></p> | |
| 1562 | + | |
| 1563 | + <?php | |
| 1564 | + echo aui()->input( | |
| 1565 | + array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1566 | + 'type' => 'text', | |
| 1567 | + 'id' => 'authcode', | |
| 1568 | + 'name' => 'authcode', | |
| 1569 | + 'placeholder' => esc_attr__( 'Authentication Code', 'userswp' ), | |
| 1570 | + 'value' => '', | |
| 1571 | + 'label' => esc_html__( 'Authentication Code', 'userswp' ), | |
| 1572 | + 'extra_attributes' => array( | |
| 1573 | + 'autocomplete' => 'one-time-code', | |
| 1574 | + ), | |
| 1575 | + ) | |
| 1576 | + ); | |
| 1577 | + | |
| 1578 | + echo aui()->button( | |
| 1579 | + array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1580 | + 'type' => 'submit', | |
| 1581 | + 'class' => 'btn btn-primary btn-block text-uppercase uwp-2fa-submit', | |
| 1582 | + 'name' => 'submit', | |
| 1583 | + 'icon' => '', | |
| 1584 | + 'content' => esc_html__( 'Log In', 'userswp' ), | |
| 1585 | + ) | |
| 1586 | + ); | |
| 1587 | + ?> | |
| 1588 | + </form> | |
| 1589 | + </div> | |
| 1590 | + | |
| 1591 | + <?php | |
| 1592 | + return ob_get_clean(); | |
| 1593 | + } | |
| 1594 | + | |
| 1595 | + public function get_wp2fa_provider_for_user( $user ) { | |
| 1596 | + if ( class_exists( '\WP2FA\Authenticator\Login' ) && method_exists( '\WP2FA\Authenticator\Login', 'get_available_providers_for_user' ) ) { | |
| 1597 | + $provider = \WP2FA\Authenticator\Login::get_available_providers_for_user( $user ); | |
| 1598 | + if ( is_array( $provider ) ) { | |
| 1599 | + $provider = key( $provider ); | |
| 1600 | + } | |
| 1601 | + | |
| 1602 | + return $provider; | |
| 1603 | + } | |
| 1604 | + | |
| 1605 | + if ( class_exists( '\WP2FA\Admin\Helpers\User_Helper' ) && method_exists( '\WP2FA\Admin\Helpers\User_Helper', 'get_enabled_method_for_user' ) ) { | |
| 1606 | + return \WP2FA\Admin\Helpers\User_Helper::get_enabled_method_for_user( $user ); | |
| 1607 | + } | |
| 1608 | + | |
| 1609 | + return ''; | |
| 1610 | + } | |
| 1611 | + | |
| 1612 | + public function get_wp2fa_backup_codes_remaining( $user ) { | |
| 1613 | + if ( class_exists( '\WP2FA\Methods\Backup_Codes' ) && method_exists( '\WP2FA\Methods\Backup_Codes', 'codes_remaining_for_user' ) ) { | |
| 1614 | + return \WP2FA\Methods\Backup_Codes::codes_remaining_for_user( $user ); | |
| 1615 | + } | |
| 1616 | + | |
| 1617 | + if ( class_exists( '\WP2FA\Authenticator\Backup_Codes' ) && method_exists( '\WP2FA\Authenticator\Backup_Codes', 'codes_remaining_for_user' ) ) { | |
| 1618 | + return \WP2FA\Authenticator\Backup_Codes::codes_remaining_for_user( $user ); | |
| 1619 | + } | |
| 1620 | + | |
| 1621 | + return 0; | |
| 1622 | + } | |
| 1623 | + | |
| 1624 | + public function validate_wp2fa_totp_authentication( $user ) { | |
| 1625 | + if ( class_exists( '\WP2FA\Methods\TOTP' ) && method_exists( '\WP2FA\Methods\TOTP', 'validate_totp_authentication' ) ) { | |
| 1626 | + return \WP2FA\Methods\TOTP::validate_totp_authentication( $user ); | |
| 1627 | + } | |
| 1628 | + | |
| 1629 | + if ( class_exists( '\WP2FA\Authenticator\Login' ) && method_exists( '\WP2FA\Authenticator\Login', 'validate_totp_authentication' ) ) { | |
| 1630 | + return \WP2FA\Authenticator\Login::validate_totp_authentication( $user ); | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + return false; | |
| 1634 | + } | |
| 1635 | + | |
| 1636 | + public function validate_wp2fa_email_authentication( $user ) { | |
| 1637 | + if ( class_exists( '\WP2FA\Authenticator\Login' ) && method_exists( '\WP2FA\Authenticator\Login', 'validate_email_authentication' ) ) { | |
| 1638 | + return \WP2FA\Authenticator\Login::validate_email_authentication( $user ); | |
| 1639 | + } | |
| 1640 | + | |
| 1641 | + if ( class_exists( '\WP2FA\Authenticator\Authentication' ) && method_exists( '\WP2FA\Authenticator\Authentication', 'validate_token' ) && isset( $_REQUEST['authcode'] ) ) { | |
| 1642 | + return \WP2FA\Authenticator\Authentication::validate_token( $user, sanitize_text_field( wp_unslash( $_REQUEST['authcode'] ) ) ); | |
| 1643 | + } | |
| 1644 | + | |
| 1645 | + return false; | |
| 1646 | + } | |
| 1647 | + | |
| 1648 | + public function validate_wp2fa_backup_codes( $user ) { | |
| 1649 | + if ( class_exists( '\WP2FA\Methods\Backup_Codes' ) && method_exists( '\WP2FA\Methods\Backup_Codes', 'validate_backup_codes' ) ) { | |
| 1650 | + return \WP2FA\Methods\Backup_Codes::validate_backup_codes( $user ); | |
| 1651 | + } | |
| 1652 | + | |
| 1653 | + if ( class_exists( '\WP2FA\Authenticator\Backup_Codes' ) && method_exists( '\WP2FA\Authenticator\Backup_Codes', 'validate_backup_codes' ) ) { | |
| 1654 | + return \WP2FA\Authenticator\Backup_Codes::validate_backup_codes( $user ); | |
| 1655 | + } | |
| 1656 | + | |
| 1657 | + return false; | |
| 1658 | + } | |
| 1659 | + | |
| 1660 | + /** | |
| 1661 | + * Validates the Wordfence 2FA code submitted from the uwp-2fa form and, | |
| 1662 | + * if valid, completes the login by setting the auth cookie. | |
| 1663 | + * | |
| 1664 | + * @since 1.2.5 | |
| 1665 | + * @package userswp | |
| 1666 | + * | |
| 1667 | + * @param WP_User $user The user attempting to complete 2FA login. | |
| 1668 | + * | |
| 1669 | + * @return void | |
| 1670 | + */ | |
| 1671 | + public function process_login_wordfence_2fa( $user ) { | |
| 1672 | + if ( ! $this->wordfence_2fa_available() ) { | |
| 1673 | + $message = aui()->alert( | |
| 1674 | + array( | |
| 1675 | + 'type' => 'error', | |
| 1676 | + 'content' => __( 'Invalid request! Please try again.', 'userswp' ), | |
| 1677 | + ) | |
| 1678 | + ); | |
| 1679 | + | |
| 1680 | + wp_send_json_error( array( 'message' => $message ) ); | |
| 1681 | + } | |
| 1682 | + | |
| 1683 | + $nonce = ( isset( $_POST['wp-auth-nonce'] ) ) ? sanitize_textarea_field( wp_unslash( $_POST['wp-auth-nonce'] ) ) : ''; | |
| 1684 | + | |
| 1685 | + if ( ! wp_verify_nonce( $nonce, 'uwp-wfls-2fa-' . $user->ID ) ) { | |
| 1686 | + $message = aui()->alert( | |
| 1687 | + array( | |
| 1688 | + 'type' => 'error', | |
| 1689 | + 'content' => __( 'Invalid request! Please try again.', 'userswp' ), | |
| 1690 | + ) | |
| 1691 | + ); | |
| 1692 | + | |
| 1693 | + wp_send_json_error( array( 'message' => $message ) ); | |
| 1694 | + } | |
| 1695 | + | |
| 1696 | + $code = isset( $_POST['authcode'] ) ? sanitize_text_field( wp_unslash( $_POST['authcode'] ) ) : ''; | |
| 1697 | + | |
| 1698 | + if ( empty( $code ) || true !== \WordfenceLS\Controller_TOTP::shared()->validate_2fa( $user, $code ) ) { | |
| 1699 | + do_action( 'wp_login_failed', $user->user_login ); | |
| 1700 | + | |
| 1701 | + $message = aui()->alert( | |
| 1702 | + array( | |
| 1703 | + 'type' => 'error', | |
| 1704 | + 'content' => __( 'Invalid verification code.', 'userswp' ), | |
| 1705 | + ) | |
| 1706 | + ); | |
| 1707 | + | |
| 1708 | + wp_send_json_error( array( 'message' => $message ) ); | |
| 1709 | + } | |
| 1710 | + | |
| 1711 | + $remember = ( isset( $_REQUEST['rememberme'] ) ) ? filter_var( $_REQUEST['rememberme'], FILTER_VALIDATE_BOOLEAN ) : false; | |
| 1712 | + | |
| 1713 | + // Complete the login the same way wp_signon() would have, now that 2FA has been verified. | |
| 1714 | + wp_set_auth_cookie( $user->ID, $remember ); | |
| 1715 | + wp_set_current_user( $user->ID ); | |
| 1716 | + | |
| 1717 | + do_action( 'wp_login', $user->user_login, $user ); | |
| 1718 | + | |
| 1719 | + $message = aui()->alert( | |
| 1720 | + array( | |
| 1721 | + 'type' => 'success', | |
| 1722 | + 'content' => __( 'Validation successful. Redirecting...', 'userswp' ), | |
| 1723 | + ) | |
| 1724 | + ); | |
| 1725 | + | |
| 1726 | + wp_send_json_success( array( 'message' => $message ) ); | |
| 1727 | + } | |
| 1728 | + | |
| 1432 | 1729 | public function process_login_2fa() { |
| 1730 | + global $wp2fa; | |
| 1731 | + | |
| 1433 | 1732 | if ( ! isset( $_POST['uwp-auth-id'], $_POST['wp-auth-nonce'] ) ) { |
| 1434 | 1733 | return; |
| 1435 | 1734 | } |
| 1436 | 1735 | |
| @@ -1435,46 +1734,70 @@ | ||
| 1435 | 1734 | } |
| 1436 | 1735 | |
| 1437 | 1736 | $auth_id = (int) $_POST['uwp-auth-id']; |
| 1438 | 1737 | $user = get_userdata( $auth_id ); |
| 1738 | + | |
| 1439 | 1739 | if ( ! $user ) { |
| 1440 | 1740 | $message = aui()->alert( |
| 1441 | - array( | |
| 1741 | + array( | |
| 1442 | 1742 | 'type' => 'error', |
| 1443 | 1743 | 'content' => __( 'Invalid user data. Please try again.', 'userswp' ), |
| 1444 | - ) | |
| 1744 | + ) | |
| 1445 | 1745 | ); |
| 1446 | 1746 | |
| 1447 | 1747 | wp_send_json_error( array( 'message' => $message ) ); |
| 1448 | 1748 | } |
| 1449 | 1749 | |
| 1450 | - global $wp2fa; | |
| 1750 | + if ( isset( $_POST['provider'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 1751 | + $provider = sanitize_textarea_field( wp_unslash( $_POST['provider'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 1752 | + } else { | |
| 1753 | + $provider = ''; | |
| 1754 | + } | |
| 1451 | 1755 | |
| 1756 | + if ( 'wordfence' === $provider ) { | |
| 1757 | + $this->process_login_wordfence_2fa( $user ); | |
| 1758 | + | |
| 1759 | + return; | |
| 1760 | + } | |
| 1761 | + | |
| 1452 | 1762 | $nonce = ( isset( $_POST['wp-auth-nonce'] ) ) ? sanitize_textarea_field( wp_unslash( $_POST['wp-auth-nonce'] ) ) : ''; |
| 1763 | + | |
| 1453 | 1764 | if ( true !== \WP2FA\Authenticator\Login::verify_login_nonce( $user->ID, $nonce ) ) { |
| 1454 | - | |
| 1455 | 1765 | $message = aui()->alert( |
| 1456 | - array( | |
| 1766 | + array( | |
| 1457 | 1767 | 'type' => 'error', |
| 1458 | 1768 | 'content' => __( 'Invalid request! Please try again.', 'userswp' ), |
| 1459 | - ) | |
| 1769 | + ) | |
| 1460 | 1770 | ); |
| 1461 | 1771 | |
| 1462 | 1772 | wp_send_json_error( array( 'message' => $message ) ); |
| 1463 | 1773 | } |
| 1464 | 1774 | |
| 1465 | - if ( isset( $_POST['provider'] ) ) { | |
| 1466 | - $provider = sanitize_textarea_field( wp_unslash( $_POST['provider'] ) ); | |
| 1467 | - $providers = \WP2FA\Authenticator\Login::get_available_providers_for_user( $user ); | |
| 1468 | - if ( isset( $providers[ $provider ] ) ) { | |
| 1469 | - $provider = $providers[ $provider ]; | |
| 1470 | - } elseif ( isset( $provider ) ) { | |
| 1471 | - $provider = $provider; | |
| 1472 | - } else { | |
| 1473 | - $provider = $provider; | |
| 1775 | + $error = ''; | |
| 1776 | + | |
| 1777 | + try { | |
| 1778 | + $is_enabled = \WP2FA\Admin\Controllers\Settings::is_provider_enabled_for_role( \WP2FA\Admin\Helpers\User_Helper::get_user_role( $user ), $provider ); | |
| 1779 | + | |
| 1780 | + if ( ! $is_enabled ) { | |
| 1781 | + $error = __( 'Invalid 2FA provider for user.', 'userswp' ); | |
| 1474 | 1782 | } |
| 1783 | + } catch ( \Exception $e ) { | |
| 1784 | + $error = $e->getMessage(); | |
| 1475 | 1785 | } |
| 1476 | 1786 | |
| 1787 | + if ( $error ) { | |
| 1788 | + do_action( 'wp_login_failed', $user->user_login ); | |
| 1789 | + | |
| 1790 | + $message = aui()->alert( | |
| 1791 | + array( | |
| 1792 | + 'type' => 'error', | |
| 1793 | + 'content' => $error | |
| 1794 | + ) | |
| 1795 | + ); | |
| 1796 | + | |
| 1797 | + wp_send_json_error( array( 'message' => $message ) ); | |
| 1798 | + } | |
| 1799 | + | |
| 1477 | 1800 | // If this is an email login, or if the user failed validation previously, lets send the code to the user. |
| 1478 | 1801 | if ( 'email' === $provider && true !== \WP2FA\Authenticator\Login::pre_process_email_authentication( $user ) ) { |
| 1479 | 1802 | |
| 1480 | 1803 | } |
| @@ -1479,17 +1802,16 @@ | ||
| 1479 | 1802 | |
| 1480 | 1803 | } |
| 1481 | 1804 | |
| 1482 | 1805 | // Validate TOTP. |
| 1483 | - if ( 'totp' === $provider && true !== \WP2FA\Authenticator\Login::validate_totp_authentication( $user ) ) { | |
| 1484 | - | |
| 1806 | + if ( 'totp' === $provider && true !== $this->validate_wp2fa_totp_authentication( $user ) ) { | |
| 1485 | 1807 | do_action( 'wp_login_failed', $user->user_login ); |
| 1486 | 1808 | |
| 1487 | 1809 | $message = aui()->alert( |
| 1488 | - array( | |
| 1810 | + array( | |
| 1489 | 1811 | 'type' => 'error', |
| 1490 | 1812 | 'content' => __( 'Invalid verification code.', 'userswp' ), |
| 1491 | - ) | |
| 1813 | + ) | |
| 1492 | 1814 | ); |
| 1493 | 1815 | |
| 1494 | 1816 | wp_send_json_error( array( 'message' => $message ) ); |
| 1495 | 1817 | } |
| @@ -1494,27 +1816,26 @@ | ||
| 1494 | 1816 | wp_send_json_error( array( 'message' => $message ) ); |
| 1495 | 1817 | } |
| 1496 | 1818 | |
| 1497 | 1819 | // Validate Email. |
| 1498 | - if ( 'email' === $provider && true !== \WP2FA\Authenticator\Login::validate_email_authentication( $user ) ) { | |
| 1499 | - | |
| 1820 | + if ( 'email' === $provider && true !== $this->validate_wp2fa_email_authentication( $user ) ) { | |
| 1500 | 1821 | do_action( 'wp_login_failed', $user->user_login ); |
| 1501 | 1822 | |
| 1502 | 1823 | if ( isset( $_REQUEST['wp-2fa-email-code-resend'] ) && 1 == $_REQUEST['wp-2fa-email-code-resend'] ) { |
| 1503 | 1824 | $message = aui()->alert( |
| 1504 | - array( | |
| 1825 | + array( | |
| 1505 | 1826 | 'type' => 'info', |
| 1506 | 1827 | 'content' => __( 'A new code has been sent.', 'userswp' ), |
| 1507 | - ) | |
| 1828 | + ) | |
| 1508 | 1829 | ); |
| 1509 | 1830 | |
| 1510 | 1831 | wp_send_json_error( array( 'message' => $message ) ); |
| 1511 | 1832 | } else { |
| 1512 | 1833 | $message = aui()->alert( |
| 1513 | - array( | |
| 1834 | + array( | |
| 1514 | 1835 | 'type' => 'error', |
| 1515 | 1836 | 'content' => __( 'Invalid verification code.', 'userswp' ), |
| 1516 | - ) | |
| 1837 | + ) | |
| 1517 | 1838 | ); |
| 1518 | 1839 | |
| 1519 | 1840 | wp_send_json_error( array( 'message' => $message ) ); |
| 1520 | 1841 | } |
| @@ -1520,17 +1841,16 @@ | ||
| 1520 | 1841 | } |
| 1521 | 1842 | } |
| 1522 | 1843 | |
| 1523 | 1844 | // Backup Codes. |
| 1524 | - if ( 'backup_codes' === $provider && true !== \WP2FA\Authenticator\Login::validate_backup_codes( $user ) ) { | |
| 1525 | - | |
| 1845 | + if ( 'backup_codes' === $provider && true !== $this->validate_wp2fa_backup_codes( $user ) ) { | |
| 1526 | 1846 | do_action( 'wp_login_failed', $user->user_login ); |
| 1527 | 1847 | |
| 1528 | 1848 | $message = aui()->alert( |
| 1529 | - array( | |
| 1849 | + array( | |
| 1530 | 1850 | 'type' => 'error', |
| 1531 | 1851 | 'content' => __( 'Invalid backup code.', 'userswp' ), |
| 1532 | - ) | |
| 1852 | + ) | |
| 1533 | 1853 | ); |
| 1534 | 1854 | |
| 1535 | 1855 | wp_send_json_error( array( 'message' => $message ) ); |
| 1536 | 1856 | } |
| @@ -1538,8 +1858,9 @@ | ||
| 1538 | 1858 | \WP2FA\Authenticator\Login::delete_login_nonce( $user->ID ); |
| 1539 | 1859 | |
| 1540 | 1860 | $rememberme = false; |
| 1541 | 1861 | $remember = ( isset( $_REQUEST['rememberme'] ) ) ? filter_var( $_REQUEST['rememberme'], FILTER_VALIDATE_BOOLEAN ) : ''; |
| 1862 | + | |
| 1542 | 1863 | if ( ! empty( $remember ) ) { |
| 1543 | 1864 | $rememberme = true; |
| 1544 | 1865 | } |
| 1545 | 1866 | |
| @@ -1546,13 +1867,17 @@ | ||
| 1546 | 1867 | wp_set_auth_cookie( $user->ID, $rememberme ); |
| 1547 | 1868 | |
| 1548 | 1869 | do_action( 'two_factor_user_authenticated', $user ); |
| 1549 | 1870 | |
| 1871 | + if ( defined( 'WP_2FA_PREFIX' ) ) { | |
| 1872 | + do_action( WP_2FA_PREFIX . 'user_authenticated', $user ); | |
| 1873 | + } | |
| 1874 | + | |
| 1550 | 1875 | $message = aui()->alert( |
| 1551 | - array( | |
| 1876 | + array( | |
| 1552 | 1877 | 'type' => 'success', |
| 1553 | 1878 | 'content' => __( 'Validation successful. Redirecting...', 'userswp' ), |
| 1554 | - ) | |
| 1879 | + ) | |
| 1555 | 1880 | ); |
| 1556 | 1881 | |
| 1557 | 1882 | wp_send_json_success( array( 'message' => $message ) ); |
| 1558 | 1883 | } |
| @@ -1649,9 +1974,12 @@ | ||
| 1649 | 1974 | } |
| 1650 | 1975 | |
| 1651 | 1976 | do_action( 'uwp_after_validate', $result, 'forgot', $data ); |
| 1652 | 1977 | |
| 1653 | - $user_data = get_user_by( 'email', $data['email'] ); | |
| 1978 | + $login_or_email = trim( $data['email'] ); | |
| 1979 | + $user_data = is_email( $login_or_email ) | |
| 1980 | + ? get_user_by( 'email', $login_or_email ) | |
| 1981 | + : get_user_by( 'login', $login_or_email ); | |
| 1654 | 1982 | |
| 1655 | 1983 | // if no user we fake it and bail |
| 1656 | 1984 | if ( ! $user_data ) { |
| 1657 | 1985 | $args = apply_filters( |
| @@ -1657,9 +1985,9 @@ | ||
| 1657 | 1985 | $args = apply_filters( |
| 1658 | 1986 | 'uwp_forgot_error_message', |
| 1659 | 1987 | array( |
| 1660 | 1988 | 'type' => 'error', |
| 1661 | - 'content' => __( 'Invalid email or user doesn\'t exists.', 'userswp' ), | |
| 1989 | + 'content' => __( 'Invalid username/email or user doesn\'t exist.', 'userswp' ), | |
| 1662 | 1990 | ) |
| 1663 | 1991 | ); |
| 1664 | 1992 | |
| 1665 | 1993 | $message = aui()->alert( $args ); |
| @@ -1709,9 +2037,8 @@ | ||
| 1709 | 2037 | } |
| 1710 | 2038 | |
| 1711 | 2039 | $as_password = apply_filters( 'uwp_forgot_message_as_password', false ); |
| 1712 | 2040 | |
| 1713 | - global $wpdb, $wp_hasher; | |
| 1714 | 2041 | $reset_link = ''; |
| 1715 | 2042 | |
| 1716 | 2043 | if ( $as_password ) { |
| 1717 | 2044 | $new_pass = wp_generate_password( 12, false ); |
| @@ -1723,17 +2050,21 @@ | ||
| 1723 | 2050 | $message .= '<p>' . sprintf( __( 'Username: %s', 'userswp' ), $user_data->user_login ) . '</p>'; |
| 1724 | 2051 | $message .= '<p>' . sprintf( __( 'Password: %s', 'userswp' ), $new_pass ) . '</p>'; |
| 1725 | 2052 | |
| 1726 | 2053 | } else { |
| 1727 | - $key = wp_generate_password( 20, false ); | |
| 1728 | - do_action( 'retrieve_password_key', $user_data->user_login, $key ); | |
| 2054 | + // Use WordPress core to generate, hash (wp_fast_hash in WP 6.8+), and store the reset key. | |
| 2055 | + // This ensures compatibility with check_password_reset_key() on all WP versions. | |
| 2056 | + $key = get_password_reset_key( $user_data ); | |
| 1729 | 2057 | |
| 1730 | - if ( empty( $wp_hasher ) ) { | |
| 1731 | - require_once ABSPATH . 'wp-includes/class-phpass.php'; | |
| 1732 | - $wp_hasher = new PasswordHash( 8, true ); | |
| 2058 | + if ( is_wp_error( $key ) ) { | |
| 2059 | + if ( wp_doing_ajax() ) { | |
| 2060 | + wp_send_json_error( $key->get_error_message() ); | |
| 2061 | + } else { | |
| 2062 | + $uwp_notices[] = array( 'forgot' => aui()->alert( array( 'type' => 'error', 'content' => $key->get_error_message() ) ) ); | |
| 2063 | + return; | |
| 2064 | + } | |
| 1733 | 2065 | } |
| 1734 | - $hashed = $wp_hasher->HashPassword( $key ); | |
| 1735 | - $wpdb->update( $wpdb->users, array( 'user_activation_key' => time() . ':' . $hashed ), array( 'user_login' => $user_data->user_login ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching | |
| 2066 | + | |
| 1736 | 2067 | $message = '<p>' . __( 'You have requested to reset your password for the following account:', 'userswp' ) . '</p>'; |
| 1737 | 2068 | $message .= home_url( '/' ) . '</p>'; |
| 1738 | 2069 | $message .= '<p>' . sprintf( __( 'Username: %s', 'userswp' ), $user_data->user_login ) . '</p>'; |
| 1739 | 2070 | $message .= '<p>' . __( 'If this was by mistake, just ignore this email and nothing will happen.', 'userswp' ) . '</p>'; |
| @@ -2026,8 +2357,21 @@ | ||
| 2026 | 2357 | unset( $uploads_result[ $upload_file_key ] ); |
| 2027 | 2358 | } |
| 2028 | 2359 | } |
| 2029 | 2360 | |
| 2361 | + global $wpdb; | |
| 2362 | + $file_field_names = $wpdb->get_col( | |
| 2363 | + $wpdb->prepare( | |
| 2364 | + "SELECT htmlvar_name FROM " . uwp_get_table_prefix() . "uwp_form_fields WHERE form_type = %s AND field_type IN ('file','image')", | |
| 2365 | + 'account' | |
| 2366 | + ) | |
| 2367 | + ); | |
| 2368 | + foreach ( $file_field_names as $file_field_name ) { | |
| 2369 | + if ( isset( $result[ $file_field_name ] ) && ! isset( $uploads_result[ $file_field_name ] ) ) { | |
| 2370 | + unset( $result[ $file_field_name ] ); | |
| 2371 | + } | |
| 2372 | + } | |
| 2373 | + | |
| 2030 | 2374 | $result = array_merge( $result, $uploads_result ); |
| 2031 | 2375 | |
| 2032 | 2376 | $args = array( |
| 2033 | 2377 | 'ID' => get_current_user_id(), |
| @@ -2315,27 +2659,50 @@ | ||
| 2315 | 2659 | $value = uwp_get_usermeta( $user_id, $htmlvar ); |
| 2316 | 2660 | |
| 2317 | 2661 | uwp_update_usermeta( $user_id, $htmlvar, '' ); |
| 2318 | 2662 | |
| 2319 | - if ( $value ) { | |
| 2663 | + if ( $value && validate_file( $value ) === 0 ) { | |
| 2320 | 2664 | $uploads = wp_upload_dir(); |
| 2321 | 2665 | $upload_path = $uploads['basedir']; |
| 2322 | - $unlink_file = untrailingslashit( $upload_path ) . '/' . ltrim( $value, '/' ); | |
| 2323 | 2666 | |
| 2324 | - if ( is_file( $unlink_file ) && file_exists( $unlink_file ) ) { | |
| 2325 | - @unlink( $unlink_file ); | |
| 2667 | + if ( strpos( $value, 'http://' ) === 0 || strpos( $value, 'https://' ) === 0 ) { | |
| 2668 | + // Get the relative url. | |
| 2669 | + $value = uwp_get_file_relative_url( $value ); | |
| 2670 | + } | |
| 2326 | 2671 | |
| 2327 | - // For avatar/banner, also remove the original (non-thumb) file. | |
| 2672 | + $unlink_file = untrailingslashit( $upload_path ) . '/' . trim( $value, '/\\' ); | |
| 2673 | + | |
| 2674 | + // Canonicalize and enforce containment inside the uploads directory before deleting. | |
| 2675 | + $real_upload_path = realpath( $upload_path ); | |
| 2676 | + $real_unlink_file = realpath( $unlink_file ); | |
| 2677 | + | |
| 2678 | + if ( $real_upload_path && $real_unlink_file && is_file( $real_unlink_file ) | |
| 2679 | + && strpos( $real_unlink_file, $real_upload_path . DIRECTORY_SEPARATOR ) === 0 ) { | |
| 2680 | + wp_delete_file( $real_unlink_file ); | |
| 2681 | + | |
| 2682 | + // For avatar/banner, also remove the original (non-thumb) file, only if it is the exact file this user cropped. | |
| 2328 | 2683 | if ( $type ) { |
| 2329 | - $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $unlink_file ); | |
| 2684 | + $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $real_unlink_file ); | |
| 2685 | + $real_unlink_ori_file = realpath( $unlink_ori_file ); | |
| 2686 | + $prev_original = get_user_meta( $user_id, '_uwp_' . $type . '_original', true ); | |
| 2687 | + $expected_original = $prev_original ? realpath( untrailingslashit( $upload_path ) . '/' . $prev_original ) : false; | |
| 2330 | 2688 | |
| 2331 | - if ( is_file( $unlink_ori_file ) && file_exists( $unlink_ori_file ) ) { | |
| 2332 | - @unlink( $unlink_ori_file ); | |
| 2689 | + if ( $expected_original && $real_unlink_ori_file && $expected_original === $real_unlink_ori_file | |
| 2690 | + && $real_unlink_ori_file !== $real_unlink_file | |
| 2691 | + && is_file( $real_unlink_ori_file ) | |
| 2692 | + && strpos( $real_unlink_ori_file, $real_upload_path . DIRECTORY_SEPARATOR ) === 0 ) { | |
| 2693 | + wp_delete_file( $real_unlink_ori_file ); | |
| 2333 | 2694 | } |
| 2334 | 2695 | } |
| 2335 | 2696 | } |
| 2336 | 2697 | } |
| 2337 | 2698 | |
| 2699 | + // Clear crop bookkeeping meta (pending upload is stored against the uploader). | |
| 2700 | + if ( $type ) { | |
| 2701 | + delete_user_meta( $user_id, '_uwp_' . $type . '_original' ); | |
| 2702 | + delete_user_meta( get_current_user_id(), '_uwp_pending_' . $type . '_upload' ); | |
| 2703 | + } | |
| 2704 | + | |
| 2338 | 2705 | wp_send_json_success(); |
| 2339 | 2706 | |
| 2340 | 2707 | wp_die(); |
| 2341 | 2708 | } |
| @@ -3813,17 +4180,26 @@ | ||
| 3813 | 4180 | $site_title = uwp_get_form_label( $field ); |
| 3814 | 4181 | $required_msg = ( ! empty( $field->is_required ) && $field->required_msg != '') ? __( stripslashes( $field->required_msg ), 'userswp' ) : ''; |
| 3815 | 4182 | $validation_text = ! empty( $field->validation_msg ) ? __( stripslashes( $field->validation_msg ), 'userswp' ) : ''; |
| 3816 | 4183 | |
| 4184 | + $is_forgot_email = ( $form_type === 'forgot' && $field->htmlvar_name === 'email' ); | |
| 4185 | + $input_type = $is_forgot_email ? 'text' : 'email'; | |
| 4186 | + if ( $is_forgot_email ) { | |
| 4187 | + $site_title = __( 'Username or Email', 'userswp' ); | |
| 4188 | + $placeholder = $site_title . ( ! empty( $field->is_required ) ? ' *' : '' ); | |
| 4189 | + } else { | |
| 4190 | + $placeholder = uwp_get_field_placeholder( $field ); | |
| 4191 | + } | |
| 4192 | + | |
| 3817 | 4193 | if ( $design_style ) { |
| 3818 | 4194 | $required = ! empty( $field->is_required ) ? ' <span class="text-danger">*</span>' : ''; |
| 3819 | 4195 | |
| 3820 | 4196 | echo aui()->input( |
| 3821 | 4197 | array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 3822 | - 'type' => 'email', | |
| 4198 | + 'type' => $input_type, | |
| 3823 | 4199 | 'id' => esc_attr( $field->htmlvar_name ), |
| 3824 | 4200 | 'name' => esc_attr( $field->htmlvar_name ), |
| 3825 | - 'placeholder' => esc_attr( uwp_get_field_placeholder( $field ) ), | |
| 4201 | + 'placeholder' => esc_attr( $placeholder ), | |
| 3826 | 4202 | 'title' => esc_html( $site_title ), |
| 3827 | 4203 | 'value' => esc_attr( wp_unslash( $value ) ), |
| 3828 | 4204 | 'required' => (bool) $field->is_required, |
| 3829 | 4205 | 'validation_text' => $validation_text != '' ? esc_attr( $validation_text ) : esc_attr( $required_msg ), |
| @@ -3859,9 +4235,9 @@ | ||
| 3859 | 4235 | |
| 3860 | 4236 | <input name="<?php echo esc_attr( $field->htmlvar_name ); ?>" |
| 3861 | 4237 | class="<?php echo esc_attr( $field->css_class ); ?> uwp_textfield <?php echo esc_attr( $bs_form_control ); ?>" |
| 3862 | 4238 | id="<?php echo esc_attr( $field->htmlvar_name ); ?>" |
| 3863 | - placeholder="<?php echo esc_attr( uwp_get_field_placeholder( $field ) ); ?>" | |
| 4239 | + placeholder="<?php echo esc_attr( $placeholder ); ?>" | |
| 3864 | 4240 | value="<?php echo esc_attr( stripslashes( $value ) ); ?>" |
| 3865 | 4241 | title="<?php echo esc_attr( $site_title ); ?>" |
| 3866 | 4242 | <?php |
| 3867 | 4243 | if ( $field->is_required == 1 ) { |
| @@ -3867,9 +4243,9 @@ | ||
| 3867 | 4243 | if ( $field->is_required == 1 ) { |
| 3868 | 4244 | echo 'required="required"'; |
| 3869 | 4245 | } |
| 3870 | 4246 | ?> |
| 3871 | - type="email" | |
| 4247 | + type="<?php echo esc_attr( $input_type ); ?>" | |
| 3872 | 4248 | /> |
| 3873 | 4249 | <span class="uwp_message_note"><?php echo wp_kses_post( uwp_get_field_description( $field ) ); ?></span> |
| 3874 | 4250 | <?php if ( $field->is_required ) { ?> |
| 3875 | 4251 | <span class="uwp_message_error invalid-feedback"><?php echo esc_html__( stripslashes( $field->required_msg ), 'userswp' ); ?></span> |