false, 'errors'=>array(), 'data'=>array() ); //only admins can do this if(!current_user_can('manage_options')){ $xout['errors'][] = 'You do not have permission to update the settings.'; wp_send_json($xout); } if(!isset($_POST['n']) || !wp_verify_nonce($_POST['n'], 'meow-settings')){ $xout['errors'][] = 'The form had expired. Please reload the page and try again.'; wp_send_json($xout); } //we need to convert string "true" and "false" to actual bools $bools = array( 'core-file_edit', 'core-xmlrpc', 'prune-active', 'login-reset_on_success', 'login-nonce', 'login-alert_on_new', 'login-alert_by_subnet', 'password-bcrypt', 'template-generator_tag', 'template-adjacent_posts', 'template-readme', 'template-noopener' ); foreach($bools AS $key){ list($k1, $k2) = explode('-', $key); if(isset($_POST[$k1][$k2])) $_POST[$k1][$k2] = $_POST[$k1][$k2] === "true"; } //convert fail window to seconds if(isset($_POST['login']['fail_window'])) $_POST['login']['fail_window'] = intval($_POST['login']['fail_window']) * 60; //now we can just stuff and save $defaults = meow_get_default_options(); $new = meow_parse_args($_POST, $defaults); //more intense scrutiny happens on pull update_option('meow_options', $new); $xout['success'] = 1; $xout['data'] = meow_get_options(true); //adjust fail window to minutes to make it easier to read $xout['data']['login']['fail_window'] = round($xout['data']['login']['fail_window']/60); wp_send_json($xout); } add_action('wp_ajax_meow_ajax_settings', 'meow_ajax_settings'); //------------------------------------------------- // Get Activity // // @param n/a // @return json function meow_ajax_activity(){ //our response $xout = array( 'success'=>false, 'errors'=>array(), 'data'=>array() ); //only admins can do this if(!current_user_can('manage_options')){ $xout['errors'][] = 'You do not have permission to search activity.'; wp_send_json($xout); } if(!isset($_POST['n']) || !wp_verify_nonce($_POST['n'], 'meow-activity')){ $xout['errors'][] = 'The form had expired. Please reload the page and try again.'; wp_send_json($xout); } $xout['success'] = true; $xout['data'] = meow_get_activity($_POST); wp_send_json($xout); } add_action('wp_ajax_meow_ajax_activity', 'meow_ajax_activity'); //------------------------------------------------- // Pardon a User // // @param n/a // @return json function meow_ajax_pardon(){ //our response $xout = array( 'success'=>false, 'errors'=>array(), 'data'=>array() ); //only admins can do this if(!current_user_can('manage_options')){ $xout['errors'][] = 'You do not have permission to search activity.'; wp_send_json($xout); } if(!isset($_POST['n']) || !wp_verify_nonce($_POST['n'], 'meow-activity')){ $xout['errors'][] = 'The form had expired. Please reload the page and try again.'; wp_send_json($xout); } global $wpdb; $id = (int) $_POST['id']; if($id <= 0 || !intval($wpdb->get_var("SELECT `id` FROM `{$wpdb->prefix}meow2_log` WHERE `id`=$id AND `type`='ban' AND `date_expires`>'" . current_time('mysql') . "'"))){ $xout['errors'][] = 'The prisoner seems to already escaped!'; } $wpdb->update( "{$wpdb->prefix}meow2_log", array( 'date_expires'=>date('Y-m-d H:i:s', strtotime("-1 second", current_time('timestamp'))), 'pardoned'=>1 ), array('id'=>$id), array('%s', '%d'), '%d'); $xout['success'] = true; $xout['data'] = meow_get_banned(); wp_send_json($xout); } add_action('wp_ajax_meow_ajax_pardon', 'meow_ajax_pardon'); //------------------------------------------------- // Rename Admin User // // @param n/a // @return json function meow_ajax_rename_admin(){ //our response $xout = array( 'success'=>false, 'errors'=>array(), 'data'=>array() ); //only admins can do this if(!current_user_can('manage_options')){ $xout['errors'][] = 'You do not have permission to rename the admin user.'; wp_send_json($xout); } if(!isset($_POST['n']) || !wp_verify_nonce($_POST['n'], 'meow-tools')){ $xout['errors'][] = 'The form had expired. Please reload the page and try again.'; wp_send_json($xout); } //no admin user? if(!username_exists('admin')){ $xout['errors'][] = 'There is no "admin" user.'; wp_send_json($xout); } $new = sanitize_user($_POST['new']); if(!strlen($new) || !validate_username($new)){ $xout['errors'][] = 'The new username is invalid.'; wp_send_json($xout); } if(username_exists($new)){ $xout['errors'][] = 'There is already a "' . $new . '" user in the system. To merge "admin" into it, click the Users tab, delete the "admin" account, and when prompted, have it reassign content (if any) to "' . $new . '".'; wp_send_json($xout); } global $wpdb; $wpdb->update("{$wpdb->prefix}users", array('user_login'=>$new), array('user_login'=>'admin'), '%s', '%s'); $xout['success'] = true; $xout['data'] = 'The "admin" user has been renamed to "' . $new . '".'; wp_send_json($xout); } add_action('wp_ajax_meow_ajax_rename_admin', 'meow_ajax_rename_admin'); //------------------------------------------------- // Reset All User Passwords // // @param n/a // @return json function meow_ajax_reset_passwords(){ //our response $xout = array( 'success'=>false, 'errors'=>array(), 'data'=>array( 'total' => 0, 'processed' => 0, 'percent' => 0, 'message' => '' ) ); //only admins can do this if(!current_user_can('manage_options')){ $xout['errors'][] = 'You do not have permission to rename the admin user.'; wp_send_json($xout); } if(!isset($_POST['n']) || !wp_verify_nonce($_POST['n'], 'meow-tools')){ $xout['errors'][] = 'The form had expired. Please reload the page and try again.'; wp_send_json($xout); } global $current_user; global $wpdb; $xout['data'] = meow_parse_args($_POST['last'], $xout['data']); foreach($xout['data'] AS $k=>$v){ if($k !== 'message') $xout['data'][$k] = (int) $v; else{ $xout['data'][$k] = wp_check_invalid_utf8($v); $utf8 = @preg_match('/^./u', 'a'); //we can sanitize whitespace better with utf8 support if($utf8){ $xout['data'][$k] = preg_replace('/\h+/u', ' ', $xout['data'][$k]); $xout['data'][$k] = preg_replace('/\v/u', "\n", $xout['data'][$k]); $xout['data'][$k] = preg_replace('/\v{3,}/u', "\n\n", $xout['data'][$k]); } } } if(!strlen($xout['data']['message'])){ $xout['errors'][] = 'A message is required.'; wp_send_json($xout); } //confirm the total, since this can change with each call $xout['data']['total'] = $wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}users`"); //grab a handful of users at a time $users = array(); $dbResult = $wpdb->get_results("SELECT `ID` FROM `{$wpdb->prefix}users` WHERE NOT(`ID`=" . intval($current_user->ID) . ") ORDER BY `ID` ASC LIMIT {$xout['data']['processed']}, 10", ARRAY_A); if(is_array($dbResult) && count($dbResult)){ foreach($dbResult AS $Row) $users[] = (int) $Row['ID']; } //is it safe to toss in the caller's id yet? if($xout['data']['total'] - $xout['data']['processed'] - count($users) === 1) $users[] = (int) $current_user->ID; //take care of business foreach($users AS $k){ //change their current password $wpdb->update( "{$wpdb->prefix}users", array('user_pass'=>wp_hash_password(wp_generate_password(35, true))), array('ID'=>$k), '%s', '%d' ); //generate a reset key $user = get_user_by('id', $k); $key = get_password_reset_key($user); $message = "{$xout['data']['message']}\n\n" . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login'); $subject = sprintf(__('[%s] Password Reset'), get_bloginfo('name')); if(!wp_mail($user->user_email, $subject, $message)){ $xout['errors'][] = 'An email message failed to get sent. The process has been aborted.'; wp_send_json($xout); } $xout['data']['processed']++; } $xout['success'] = true; $xout['data']['percent'] = round($xout['data']['processed'] / $xout['data']['total'] * 100, 2); wp_send_json($xout); } add_action('wp_ajax_meow_ajax_reset_passwords', 'meow_ajax_reset_passwords'); ?>