403Webshell
Server IP : 8.134.250.228  /  Your IP : 216.73.217.42
Web Server : Apache
System : Linux iZ7xv33p9e9ivk7yhmj7ibZ 5.10.134-18.al8.x86_64 #1 SMP Fri Dec 13 16:56:53 CST 2024 x86_64
User : www ( 1000)
PHP Version : 8.0.26
Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /www/wwwroot/www.gobluemade.com/wp-content/plugins/sql-batch-replace/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /www/wwwroot/www.gobluemade.com/wp-content/plugins/sql-batch-replace/func.php
<?php
/*
 * @Author: 子比主题老唐-Qinver
 * @Url: zibll.com
 * @Date: 2023-10-12 12:18:41
 * @LastEditTime: 2025-10-17 10:12:42
 * @Read me : 本工具为免费开源工具,您可以自由使用和分享,如您需要分享或二次开发,请务必保留并在显眼处体现作者名,以及www.zibll.com的网站
 * @Read me : 不要用于任何商业用途,否则将依法追究相关责任,谢谢合作!
 */

namespace zib\sql;

class SqlReplace
{
    public $plugin_name     = '';
    public $admin_page_suge = 'sql-batch-replace';

    public function __construct()
    {
        add_action('admin_print_footer_scripts', [$this, 'home_url_remind']);
        add_action('admin_menu', [$this, 'admin_menu']);
        add_filter('plugin_action_links_' . SQL_REPLACE_PLUGIN_BASENAME, [$this, 'action_links']);

        add_action('wp_ajax_sql_replace_next', [$this, 'ajax_next']);
        add_action('wp_ajax_sql_replace_submit', [$this, 'ajax_submit']);
    }

    //提醒
    public function home_url_remind()
    {
        if (!isset($GLOBALS['pagenow']) || 'options-general.php' !== $GLOBALS['pagenow']) {
            return;
        }

        $home_url = home_url();

        echo '<style>
        .admin-url-set-warning{
            display:none;
        }</style>
        <script>
        (function ($, document) {$(document).ready(function ($) {
            var admin_options_url_input = $(\'.options-general-php input#home\');
            if (admin_options_url_input.length) {
                var html = \'<div style="color: #0068f0;background: #eaf4fb;padding: 10px 20px;border-radius: 6px;border: 1px solid #bde6ff;margin-top: 6px;"><div><div style="margin-bottom: 10px;">' . __('如需修改URL,请使用数据库批量替换插件修改网站地址,一键完美替换', SQL_REPLACE_TEXT_DOMAIN) . '</div><a class="button button-primary" href="' . admin_url('options-general.php?page=sql-batch-replace&old=' . $home_url) . '">' . __('立即修改', SQL_REPLACE_TEXT_DOMAIN) . '</a></div></div>\';
                admin_options_url_input.after(html);
                admin_options_url_input.attr(\'readonly\',true);
                $(\'.options-general-php input#siteurl\').attr(\'readonly\',true);
            }
        });})(jQuery, document);
        </script>';
    }

    public function admin_menu()
    {
        if (is_multisite() && (!is_main_site() || !is_super_admin())) {
            return;
        }
        $menu = __('数据库批量替换', SQL_REPLACE_TEXT_DOMAIN);
        add_options_page($menu, $menu, 'manage_options', $this->admin_page_suge, [$this, 'admin_page']);

    }

    public function action_links($links)
    {
        if (is_multisite() && (!is_main_site() || !is_super_admin())) {
            return $links;
        }

        $osslink = array('<a href="options-general.php?page=' . $this->admin_page_suge . '">' . __('开始替换', SQL_REPLACE_TEXT_DOMAIN) . '</a>');
        return array_merge($osslink, $links);
    }

    public function script_json()
    {
        $data = array(
            'ajax_url'    => admin_url('admin-ajax.php'),
            'nonce'       => wp_create_nonce('sql-replace-nonce'),
            'replace_url' => admin_url('admin-ajax.php?action=sql-replace'),
            'lang'        => array(
                'replace_reminder'        => __('请确认将{old}替换为{new}', SQL_REPLACE_TEXT_DOMAIN),
                'replace_count_reminder'  => __('共计替换{count}条数据,替换后无法撤回,请确保已备份数据库!', SQL_REPLACE_TEXT_DOMAIN),
                'query_title'             => __('替换明细:表 => 列 => 数量 || 序列化数量', SQL_REPLACE_TEXT_DOMAIN),
                'requery_btn'             => __('重新查询', SQL_REPLACE_TEXT_DOMAIN),
                'not_reminder'            => __('没有找到匹配的替换内容', SQL_REPLACE_TEXT_DOMAIN),
                'reconfirm_reminder'      => __('请再次确认替换【{old}】为【{new}】吗?', SQL_REPLACE_TEXT_DOMAIN),
                'parameter_error'         => __('替换参数错误,请刷新后重试', SQL_REPLACE_TEXT_DOMAIN),
                'loading_text'            => __('正在批量替换中,请稍后...', SQL_REPLACE_TEXT_DOMAIN),
                'replace_title'           => __('数据替换明细:表 => 列 => 数量', SQL_REPLACE_TEXT_DOMAIN),
                'replace_serialize_title' => __('序列化数据替换明细:表 => 列 => 数量', SQL_REPLACE_TEXT_DOMAIN),
                'replace_success_title'   => __('操作成功', SQL_REPLACE_TEXT_DOMAIN),
                'replace_success_text'    => __('已将{old}替换为{new}', SQL_REPLACE_TEXT_DOMAIN),
            ),
        );

        return '<script>_sql = ' . json_encode($data) . '</script>';
    }

    public function admin_page()
    {

        $old_val = !empty($_GET['old']) ? $_GET['old'] : '';

        $css_link = '<link rel="stylesheet" href="' . SQL_REPLACE_URL . '/assets/css/main.min.css?ver=' . SQL_REPLACE_VERSION . '">'; //main
        $js_link  = $this->script_json();
        $js_link .= '<script src="' . SQL_REPLACE_URL . '/assets/js/main.min.js?ver=' . SQL_REPLACE_VERSION . '"></>';

        $input = '<div class="">
                    <div class="sql-st">' . __('将', SQL_REPLACE_TEXT_DOMAIN) . '</div>
                    <input class="sql-input-old" type="text" name="old" value="' . $old_val . '">
                </div>
                <div class="">
                <div class="sql-st">' . __('替换为', SQL_REPLACE_TEXT_DOMAIN) . '</div>
                    <input class="sql-input-new" type="text" name="new" value="">
                </div>';

        $desc = __('快速的批量替换数据库中的旧内容为新的内容,适用于网站换域名、加证书后网址改为https、更换云储存后批量更换媒体链接等操作', SQL_REPLACE_TEXT_DOMAIN) . '
        <br>' . __('操作仅需两步,全程自动化,快捷方便!', SQL_REPLACE_TEXT_DOMAIN) . '
        <br>' . __('工具会自动分析数据库表,支持所有主题及插件!', SQL_REPLACE_TEXT_DOMAIN) . '
        <br>' . __('自动判断序列化数据,序列化数据自动转义并替换,确保数据安全,真正意义上解决SQL命令批量替换会出现的各种bug!', SQL_REPLACE_TEXT_DOMAIN) . ' <a target="_blank" href="https://www.zibll.com/18629.html" class="sql-ad">' . __('【了解相关原理】', SQL_REPLACE_TEXT_DOMAIN) . '</a>';

        $warning_desc = '<div calss="">' . __('注意事项:', SQL_REPLACE_TEXT_DOMAIN) . '</div>';
        $warning_desc .= '<div calss="">' . __('1.使用此工具前,请务必先备份数据库!!!!以避免操作错误带来的损失', SQL_REPLACE_TEXT_DOMAIN) . '</div>';
        $warning_desc .= '<div calss="">' . __('2.替换时,请勿输入很短的替换值,容易误修改', SQL_REPLACE_TEXT_DOMAIN) . '</div>';
        $warning_desc .= '<div calss="">' . __('3.此工具仅批量修改数据库内容,对修改后会导致的结果无法判断,如果您不清楚您的操作会带来什么结果,请谨慎操作', SQL_REPLACE_TEXT_DOMAIN) . '</div>';
        $warning_desc .= '<div calss="">' . __('4.此工具可无脑使用,但仍建议先了解数据库相关原理', SQL_REPLACE_TEXT_DOMAIN) . '<a target="_blank" href="https://www.zibll.com/18629.html" class="sql-ad">' . __('【了解相关原理】', SQL_REPLACE_TEXT_DOMAIN) . '</a></div>';

        $warning_desc = '<div class="sql-warning">' . $warning_desc . '</div>';
        $input        = '<div class="sql-ks">' . __('开始替换', SQL_REPLACE_TEXT_DOMAIN) . '</div><div class="sql-input">' . $input . '</div>';
        $input .= '<div class="sql-btns"><a href="javascript:;" class="sql-btn sql-next">' . __('下一步', SQL_REPLACE_TEXT_DOMAIN) . '</a><a href="javascript:;" class="sql-btn sql-submit" style="display: none;">' . __('确认替换', SQL_REPLACE_TEXT_DOMAIN) . '</a></div>';

        $input .= '<div class="sql-notice">' . $desc . '</div>';
        $html = '<div class="wrap"><div class="sql-replace-wrap"><div class="sql-header"><div class="sql-titel">' . __('数据库批量替换小工具', SQL_REPLACE_TEXT_DOMAIN) . '</div><div class="sql-by">By:zibll-老唐 | <a target="_blank" href="https://www.zibll.com/19369.html">' . __('查看官方教程', SQL_REPLACE_TEXT_DOMAIN) . '</a></div></div>' . $warning_desc . '<div class="sql-content-wrap">' . $input . '</div><div class="sql-footer"><a target="_blank" href="https://www.zibll.com" class="sql-ad">AD:' . __('zibll子比主题是一款功能强大、设计精美的资讯、商城、社区、论坛主题,如果您还不知道,那就OUT了,点此了解详情', SQL_REPLACE_TEXT_DOMAIN) . '</a></div></div></div>';

        echo $css_link;
        echo $html;
        echo $js_link;
    }

    public function get_db_table_args()
    {

        global $wpdb;

        $args = array(
            array(
                'table_name'  => $wpdb->posts,
                'column_name' => 'post_content',
            ),
            array(
                'table_name'  => $wpdb->posts,
                'column_name' => 'guid',
            ),
            array(
                'table_name'  => $wpdb->posts,
                'column_name' => 'post_excerpt',
            ),
            array(
                'table_name'  => $wpdb->posts,
                'column_name' => 'post_title',
            ),
            array(
                'table_name'  => $wpdb->postmeta,
                'column_name' => 'meta_value',
            ),
            array(
                'table_name'  => $wpdb->comments,
                'column_name' => 'comment_content',
            ),
            array(
                'table_name'  => $wpdb->comments,
                'column_name' => 'comment_author_url',
            ),
            array(
                'table_name'  => $wpdb->commentmeta,
                'column_name' => 'meta_value',
            ),
            array(
                'table_name'  => $wpdb->users,
                'column_name' => 'user_url',
            ),
            array(
                'table_name'  => $wpdb->usermeta,
                'column_name' => 'meta_value',
            ),
            array(
                'table_name'  => $wpdb->termmeta,
                'column_name' => 'meta_value',
            ),
            array(
                'table_name'  => $wpdb->term_taxonomy,
                'column_name' => 'description',
            ),
        );

        //排除
        $eliminate_table_names   = array_column($args, 'table_name');
        $eliminate_table_names[] = $wpdb->options;
        //获取其他
        $sql    = "SELECT t.TABLE_NAME as table_name ,c.COLUMN_NAME as column_name FROM information_schema.TABLES t,INFORMATION_SCHEMA.Columns c WHERE c.TABLE_NAME=t.TABLE_NAME AND c.TABLE_SCHEMA = '" . DB_NAME . "' AND c.DATA_TYPE in ('longtext','text') AND t.TABLE_NAME NOT IN ('" . implode("','", $eliminate_table_names) . "')";
        $result = $wpdb->get_results($sql);
        if ($result) {
            $args = array_merge($args, $result);
        }

        $args[] = array(
            'table_name'  => $wpdb->options, //
            'column_name' => 'option_value',
        );

        return $args;
    }

    //执行替换数据库
    public function db_replace($old, $new)
    {
        global $wpdb;
        $is_str_strlen_same = strlen($old) === strlen($new);
        $table_args         = $this->get_db_table_args();

        $data = array(
            'serialize' => array(
                'count'  => 0,
                'detail' => array(),
            ), //序列化数据
            'routine'   => array(
                'count'  => 0,
                'detail' => array(),
            ), //普通常规数据
        );

        //如果前后字串符数量不同,则先执行序列化数据替换。
        if (!$is_str_strlen_same) {
            $data['serialize'] = $this->db_replace_serialize($old, $new);

            //如果由于超时,没有全部替换完成,则先返回,等待浏览器再次发送请求
            if (!empty($data['serialize']['time_over'])) {
                $data['time_over'] = true;
                return $data;
            }
        }

        //处理非序列化数据,或者前后字符串数量一致的
        foreach ($table_args as $args) {
            $args      = (array) $args;
            $s_name    = $args['table_name'];
            $s_columns = $args['column_name'];
            $sql       = "UPDATE `$s_name` SET `$s_columns` = replace(`$s_columns`,'$old','$new')";
            if (!$is_str_strlen_same) {
                $sql .= " WHERE `$s_columns` NOT LIKE '%{%' OR `$s_columns` NOT LIKE '%}'";
            }

            $count                       = $wpdb->query($sql);
            $data['routine']['detail'][] = array(
                'table_name'  => $s_name,
                'column_name' => $s_columns,
                'count'       => $count,
                'sql'         => $sql,
            );
            $data['routine']['count'] += $count;

        }

        return $data;
    }

    //替换数据库中序列化字符串
    public function db_replace_serialize($old, $new)
    {

        global $wpdb;
        $time_over_second = 8; //函数最大执行时间,超时后由前端自动重新发起请求,单位秒
        $table_args       = $this->get_db_table_args();
        $data             = array(
            'count'  => 0,
            'detail' => array(),
        );

        //开始计时
        $start_time = microtime(true);
        foreach ($table_args as $args) {
            $args      = (array) $args;
            $s_name    = $args['table_name'];
            $s_columns = $args['column_name'];

            $sql_paged_size  = 100; //每次查询数量
            $sql_paged_start = 0;

            for ($i = 0; $i < 1000000000000000000000000; $i++) {
                $sql     = "SELECT `$s_columns` as `s_val` FROM `$s_name` WHERE `$s_columns` like '%$old%' and `$s_columns` LIKE '%{%' and `$s_columns` LIKE '%}' LIMIT $sql_paged_start,$sql_paged_size";
                $results = $wpdb->get_results($sql);

                if ($results && is_array($results)) {
                    $i = 0;
                    foreach ($results as $result) {
                        if ($this->db_save_serialize_data($s_name, $s_columns, $result->s_val, $old, $new)) {
                            $i++;
                        }
                    }

                    $data['detail'][] = array(
                        'table_name'  => $s_name,
                        'column_name' => $s_columns,
                        'count'       => $i,
                        'sql'         => $sql,
                    );

                    $data['count'] += $i;
                }

                $sql_paged_start += $sql_paged_size;

                //判断是否超时,超时直接退出循环
                if ((microtime(true) - $start_time) > $time_over_second) {
                    $data['time_over'] = true;
                    return $data;
                }

                if (count($results) < $sql_paged_size) {
                    break;
                }
            }
        }

        return $data;
    }

    //执行保存序列化数据
    public function db_save_serialize_data($s_name, $s_columns, $result, $old, $new)
    {
        global $wpdb;

        if (is_serialized($result)) {
            $new_val = $this->serialize_data_replace(maybe_unserialize($result), $old, $new);
        } else {
            $new_val = str_replace($old, $new, $result);
        }

        $new_val = maybe_serialize($new_val);
        return $wpdb->update($s_name, array($s_columns => $new_val), array($s_columns => $result));
    }

    //替换序列化数据中的内容
    public function serialize_data_replace($result, $old, $new)
    {
        //以下为递归替换
        if (is_array($result)) {
            foreach ($result as $k => $v) {
                $result[$k] = $this->serialize_data_replace($v, $old, $new, $k);
            }
        } elseif (is_object($result)) {
            $result = (object) $this->serialize_data_replace((array) $result, $old, $new);
        } else {
            $result = str_replace($old, $new, $result);
        }

        return $result;
    }

    //搜索数据库,返回匹配数量明细
    public function db_select($key, $new = '')
    {
        global $wpdb;
        $is_str_strlen_same = true;
        if ($new && strlen($new) !== strlen($key)) {
            $is_str_strlen_same = false;
        }

        $table_args = $this->get_db_table_args();
        $data       = array();
        $statistics = array(
            'count'           => 0,
            'serialize_count' => 0,
        ); //统计数据
        foreach ($table_args as $args) {
            $args      = (array) $args;
            $s_name    = $args['table_name'];
            $s_columns = $args['column_name'];
            $sql       = "SELECT count(*) FROM `$s_name` WHERE `$s_columns` like '%$key%'";
            $count     = $wpdb->get_var($sql);
            $statistics['count'] += $count;

            if ($count) {
                $serialize_count = 0;
                $serialize_sql   = '';
                if (!$is_str_strlen_same) {
                    $serialize_sql   = $sql . " and `$s_columns` LIKE '%{%' and `$s_columns` LIKE '%}'";
                    $serialize_count = $wpdb->get_var($serialize_sql);
                    $statistics['serialize_count'] += $serialize_count;
                }

                $data[] = array(
                    'table_name'      => $s_name,
                    'column_name'     => $s_columns,
                    'count'           => $count,
                    'serialize_count' => $serialize_count,
                    'sql'             => $sql,
                    'serialize_sql'   => $serialize_sql,
                );
            }

        }

        return array(
            'data'       => $data,
            'statistics' => $statistics,
        );
    }

    //第一步的AJAX操作,先进行查询并返回
    public function ajax_next()
    {
        //执行跨域安全检查
        if (!isset($_REQUEST['nonce']) || !wp_verify_nonce($_REQUEST['nonce'], 'sql-replace-nonce')) {
            wp_send_json_error(__('环境异常或登录状态已失效,请刷新页面重试', SQL_REPLACE_TEXT_DOMAIN));
        }

        //执行管理员权限验证
        if (!is_super_admin()) {
            wp_send_json_error(__('权限不足或登录状态已失效,请刷新页面重试', SQL_REPLACE_TEXT_DOMAIN));
        }

        $old = esc_sql($_POST['old']);
        $new = esc_sql($_POST['new']);

        if (!$old) {
            wp_send_json_error(__('请输入需要替换的旧内容', SQL_REPLACE_TEXT_DOMAIN));
        }

        if (!$new) {
            wp_send_json_error(__('请输入需要替换的新内容', SQL_REPLACE_TEXT_DOMAIN));
        }

        if ($new === $old) {
            wp_send_json_error(__('新内容不能与旧内容相同', SQL_REPLACE_TEXT_DOMAIN));
        }

        $send_msg = '';
        if (strlen($new) < 12 || strlen($old) < 12) {
            $send_msg = __('您输入的内容字符数量较少,替换时容易出现误修改情况,请认真确认', SQL_REPLACE_TEXT_DOMAIN);
        }

        $db_select = $this->db_select($old, $new);
        if (empty($db_select['data'])) {
            wp_send_json_error(__('数据库未查询到可替换的内容[' . $old . ']', SQL_REPLACE_TEXT_DOMAIN));
        }

        if ($db_select['statistics']['serialize_count'] > 500) {
            $estimated_time = ((int) ceil($db_select['statistics']['serialize_count'] / 160)) * 20;
            $send_msg .= $send_msg ? '<br>' : '';
            $send_msg .= str_replace('{time}', $estimated_time, __('需要替换的序列化数据较多,大约需要{time}秒,请耐心等待!', SQL_REPLACE_TEXT_DOMAIN));
        }

        wp_send_json_success(['msg' => $send_msg, 'old' => $old, 'new' => $new, 'data' => $db_select['data'], 'statistics' => $db_select['statistics'], 'num_queries' => get_num_queries(), 'timer_stop' => timer_stop(0, 6) * 1000 . 'ms']);
    }

    //第二步的AJAX操作,替换数据
    public function ajax_submit()
    {
        //执行跨域安全检查
        if (!isset($_REQUEST['nonce']) || !wp_verify_nonce($_REQUEST['nonce'], 'sql-replace-nonce')) {
            wp_send_json_error(__('环境异常或登录状态已失效,请刷新页面重试', SQL_REPLACE_TEXT_DOMAIN));
        }

        //执行管理员权限验证
        if (!is_super_admin()) {
            wp_send_json_error(__('权限不足或登录状态已失效,请刷新页面重试', SQL_REPLACE_TEXT_DOMAIN));
        }

        $old = esc_sql($_POST['old']);
        $new = esc_sql($_POST['new']);

        if (!$old) {
            wp_send_json_error(__('请输入需要替换的旧内容', SQL_REPLACE_TEXT_DOMAIN));
        }

        if (!$new) {
            wp_send_json_error(__('请输入需要替换的新内容', SQL_REPLACE_TEXT_DOMAIN));
        }

        if ($new === $old) {
            wp_send_json_error(__('新内容不能与旧内容相同', SQL_REPLACE_TEXT_DOMAIN));
        }

        //执行替换操作
        $db_result = $this->db_replace($old, $new);

        //返回执行结果数据
        $count     = $db_result['routine']['count'] + $db_result['serialize']['count'];
        $time_over = !empty($db_result['time_over']); //是否是超时,如果超时,则自动重新发起替换
        $send_msg  = $time_over ? '' : __('数据库替换完成,如您替换了网站域名,请自行跳转到新地址访问', SQL_REPLACE_TEXT_DOMAIN);

        //刷新所有缓存
        wp_cache_flush();

        wp_send_json_success(['msg' => $send_msg, 'time_over' => $time_over, 'num_queries' => get_num_queries(), 'timer_stop' => timer_stop(0, 6) * 1000 . 'ms', 'count' => $count, 'old' => $old, 'new' => $new, 'data' => $db_result]);
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit