HEX
Server: LiteSpeed
System: Linux server490.bertina.biz 5.14.0-687.31.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Sat Aug 1 05:38:01 EDT 2026 x86_64
User: parskavirpaya (1252)
PHP: 8.1.34
Disabled: mail, show_source, system, shell_exec, passthru, exec, popen
Upload Files
File: /home/parskavirpaya/public_html/wp-content/plugins/interlinks-manager/class-daim-ajax.php
<?php
/**
 * This file contains the class Daim_Ajax, used to include ajax actions.
 *
 * @package interlinks-manager
 */

/**
 * This class should be used to include ajax actions.
 */
class Daim_Ajax {

	/**
	 * The instance of the Daim_Ajax class.
	 *
	 * @var Daim_Ajax
	 */
	protected static $instance = null;

	/**
	 * The instance of the Daim_Shared class.
	 *
	 * @var Daim_Shared
	 */
	private $shared = null;

	/**
	 * The constructor of the Daim_Ajax class.
	 */
	private function __construct() {

		// Assign an instance of the plugin info.
		$this->shared = Daim_Shared::get_instance();

		// Ajax requests --------------------------------------------------------.

		// For logged-in and not-logged-in users --------------------------------.
		add_action( 'wp_ajax_track_internal_link', array( $this, 'track_internal_link' ) );
		add_action( 'wp_ajax_nopriv_track_internal_link', array( $this, 'track_internal_link' ) );

		// For logged-in users --------------------------------------------------.
		add_action( 'wp_ajax_daim_wizard_generate_ail', array( $this, 'daim_wizard_generate_ail' ) );
		add_action( 'wp_ajax_daim_get_taxonomies', array( $this, 'daim_get_taxonomies' ) );
		add_action( 'wp_ajax_daim_get_terms', array( $this, 'daim_get_terms' ) );
	}

	/**
	 * Return an istance of this class.
	 */
	public static function get_instance() {

		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Ajax handler used to track internal links in the front-end.
	 */
	public function track_internal_link() {

		// Check the referer.
		if ( ! check_ajax_referer( 'daim', 'security', false ) ) {
			echo 'Invalid AJAX Request';
			die();}

		// Sanitization.
		$link_type      = isset( $_POST['link_type'] ) && sanitize_key( $_POST['link_type'] ) === 'ail' ? $link_type = 0 : $link_type = 1;
		$source_post_id = isset( $_POST['source_post_id'] ) ? intval( $_POST['source_post_id'], 10 ) : null;
		$target_url     = isset( $_POST['target_url'] ) ? mb_substr( esc_url_raw( wp_unslash( $_POST['target_url'] ) ), 0, 2038 ) : null;

		// Validation.
		if ( is_null( $source_post_id ) || is_null( $target_url ) ) {
			echo 'invalid-data';
			die();
		}

		// Get the current time.
		$date     = current_time( 'mysql' );
		$date_gmt = current_time( 'mysql', 1 );

		/**
		 * Remove all the filter associated with 'the_title' to get with the
		 * function get_the_title() the raw title saved in the posts table.
		 */
		remove_all_filters( 'the_title' );
		$post_title = get_the_title( $source_post_id );

		// Verify if the post with the link exists.
		if ( get_post_status( $source_post_id ) === false ) {
			echo 'The post doesn\'t exists.';
			die(); }

		// Save into the database.
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$query_result = $wpdb->query(
			$wpdb->prepare(
				"INSERT INTO {$wpdb->prefix}daim_hits SET 
            source_post_id = %d,
            post_title = %s,
            post_permalink = %s,
            post_edit_link = %s,
            target_url = %s,
            link_type = %s,
            date = %s,
            date_gmt = %s",
				$source_post_id,
				$post_title,
				get_the_permalink( $source_post_id ),
				get_edit_post_link( $source_post_id, 'url' ),
				$target_url,
				$link_type,
				$date,
				$date_gmt
			)
		);

		if ( false === $query_result ) {
			echo 'error';
		} else {
			echo 'success';
		}

		die();
	}

	/**
	 * Ajax handler used to generate the AIL based on the data available in the table of the Wizard menu.
	 *
	 * This method is called when the "Generate Autolinks" button available in the Wizard menu is clicked.
	 */
	public function daim_wizard_generate_ail() {

		// Check the referer.
		if ( ! check_ajax_referer( 'wizard_nonce', 'security', false ) ) {
			echo 'Invalid AJAX Request';
			die();
		}

		// Check the capability.
		if ( ! current_user_can( get_option( $this->shared->get( 'slug' ) . '_wizard_menu_required_capability' ) ) ) {
			echo 'Invalid Capability';
			die();
		}

		// Get the default values of the AIL from the plugin options.
		$default_title                            = get_option( $this->shared->get( 'slug' ) . '_default_title' );
		$default_open_new_tab                     = get_option( $this->shared->get( 'slug' ) . '_default_open_new_tab' );
		$default_use_nofollow                     = get_option( $this->shared->get( 'slug' ) . '_default_use_nofollow' );
		$default_activate_post_types              = get_option( $this->shared->get( 'slug' ) . '_default_activate_post_types' );
		$default_categories                       = get_option( $this->shared->get( 'slug' ) . '_default_categories' );
		$default_tags                             = get_option( $this->shared->get( 'slug' ) . '_default_tags' );
		$default_term_group_id                    = get_option( $this->shared->get( 'slug' ) . '_default_term_group_id' );
		$default_case_insensitive_search          = get_option( $this->shared->get( 'slug' ) . '_default_case_insensitive_search' );
		$default_left_boundary                    = get_option( $this->shared->get( 'slug' ) . '_default_string_before' );
		$default_right_boundary                   = get_option( $this->shared->get( 'slug' ) . '_default_string_after' );
		$default_keyword_before                   = get_option( $this->shared->get( 'slug' ) . '_default_keyword_before' );
		$default_keyword_after                    = get_option( $this->shared->get( 'slug' ) . '_default_keyword_after' );
		$default_max_number_autolinks_per_keyword = get_option( $this->shared->get( 'slug' ) . '_default_max_number_autolinks_per_keyword' );
		$default_priority                         = get_option( $this->shared->get( 'slug' ) . '_default_priority' );

		// get the name.
		$name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : null;

		// get the category_id.
		$category_id = isset( $_POST['category_id'] ) ? intval( $_POST['category_id'], 10 ) : null;

		// get the data of the table.
		$table_data_a = isset( $_POST['table_data'] ) ? $this->shared->sanitize_table_data( wp_unslash( $_POST['table_data'] ) ) : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		// Validation -------------------------------------------------------------------------------------------------.
		if ( mb_strlen( $name ) === 0 || mb_strlen( $name ) > 100 ) {
			echo 'invalid name';
			die();
		}

		global $wpdb;

		// add the new data.
		$values        = array();
		$place_holders = array();
		$query         = "INSERT INTO {$wpdb->prefix}daim_autolinks (
            name,
            category_id,
            keyword,
            url,
            title,
            string_before,
            string_after,
            keyword_before,
            keyword_after,
            activate_post_types,
            categories,
            tags,
            term_group_id,
            max_number_autolinks,
            case_insensitive_search,
            open_new_tab,
            use_nofollow,
            priority
        ) VALUES ";

		// Set the PHP "Max Execution Time" and "Memory Limit" based on the values defined in the options.
		$this->shared->set_met_and_ml();

		foreach ( $table_data_a as $row_index => $row_data ) {

			$keyword = sanitize_text_field( $row_data[0] );
			$url     = substr( esc_url_raw( 'https://example.com' . $row_data[1] ), 19 );
			$title   = sanitize_text_field( $row_data[2] );

			// validation on "Keyword".
			if ( strlen( trim( $keyword ) ) === 0 || strlen( $keyword ) > 255 ) {
				continue;
			}

			/*
			 * Do not allow only numbers as a keyword. Only numbers in a keyword would cause the index of the protected block to
			 * be replaced. For example the keyword "1" would cause the "1" present in the index of the following protected
			 * blocks to be replaced with an autolink:
			 *
			 * - [pb]1[/pb]
			 * - [pb]31[/pb]
			 * - [pb]812[/pb]
			 */
			if ( preg_match( '/^\d+$/', $keyword ) === 1 ) {
				continue;
			}

			/**
			 * Do not allow to create specific keywords that would be able to replace the start delimiter of the
			 * protected block [pb], part of the start delimiter, the end delimited [/pb] or part of the end delimiter.
			 */
			if ( preg_match( '/^\[$|^\[p$|^\[pb$|^\[pb]$|^\[\/$|^\[\/p$|^\[\/pb$|^\[\/pb\]$|^\]$|^b\]$|^pb\]$|^\/pb\]$|^p$|^pb$|^pb\]$|^\/$|^\/p$|^\/pb$|^\/pb]$|^b$|^b\$/i', $keyword ) === 1 ) {
				continue;
			}

			/**
			 * Do not allow to create specific keywords that would be able to replace the start delimiter of the
			 * autolink [ail], part of the start delimiter, the end delimited [/ail] or part of the end delimiter.
			 */
			if ( ! preg_match( '/^\[$|^\[a$|^\[ai$|^\[ail$|^\[ail\]$|^a$|^ai$|^ail$|^ail\]$|^i$|^il$|^il\]$|^l$|^l\]$|^\]$|^\[$|^\[\/$|^\[\/a$|^\[\/ai$|^\[\/ail$|^\[\/ail\]$|^\/$|^\/]$|^\/a$|^\/ai$|^\/ail$|^\/ail\]$/i', $keyword ) === 1 ) {
				continue;
			}

			// Validation on "Target".
			if ( strlen( trim( $url ) ) === 0 ||
				strlen( $keyword ) > 2083 ||
				! preg_match( '/^(?!(http|https|fpt|file):\/\/)[-A-Za-z0-9+&@#\/%?=~_|$!:,.;]+$/', $url ) ) {
				continue;
			}

			// Validation on "Title".
			if ( strlen( $title ) > 1024 ) {
				continue;
			}

			// If the title is not defined use the default title.
			if ( strlen( trim( $title ) ) === 0 ) {
				$title = $default_title;
			}

			array_push(
				$values,
				$name,
				$category_id,
				$keyword,
				$url,
				$title,
				$default_left_boundary,
				$default_right_boundary,
				$default_keyword_before,
				$default_keyword_after,
				maybe_serialize( $default_activate_post_types ),
				maybe_serialize( $default_categories ),
				maybe_serialize( $default_tags ),
				$default_term_group_id,
				$default_max_number_autolinks_per_keyword,
				$default_case_insensitive_search,
				$default_open_new_tab,
				$default_use_nofollow,
				$default_priority
			);

			$place_holders[] = "(
            '%s',
            '%d',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%d',
            '%d',
            '%d',
            '%d',
            '%d',
            '%d'
            )";

		}

		if ( count( $values ) > 0 ) {

			// Add the rows.
			$query .= implode( ', ', $place_holders );
			//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared -- The query is prepared here.
			$result = $wpdb->query(
				$wpdb->prepare( $query, $values )
			);
			//phpcs:enable

			if ( false === $result ) {
				$output = 'error';
			} else {
				$output = $result;
			}
		} else {

			// Do not add the rows and set $output to 0 as the number of rows added.
			$output = 0;

		}

		if ( 'error' === $output ) {
			$this->shared->save_dismissible_notice(
				__( 'Now rows have been added.', 'interlinks-manager'),
				'error'
			);
		} else {
			$this->shared->save_dismissible_notice(
				$output . ' ' . __( 'rows have been added.', 'interlinks-manager'),
				'updated'
			);
		}

		// Send output.
		echo esc_html( $output );
		die();
	}

	/**
	 * Get the list of taxonomies associated with the provided post type.
	 */
	public function daim_get_taxonomies() {

		// check the referer.
		if ( ! check_ajax_referer( 'daim', 'security', false ) ) {
			esc_html_e( 'Invalid AJAX Request', 'interlinks-manager');
			die();
		}

		// check the capability.
		if ( ! current_user_can( get_option( $this->shared->get( 'slug' ) . '_term_groups_menu_required_capability' ) ) ) {
			esc_html_e( 'Invalid Capability', 'interlinks-manager');
			die();
		}

		// get the data.
		$post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : null;

		$taxonomies = get_object_taxonomies( $post_type );

		$taxonomy_obj_a = array();
		if ( is_array( $taxonomies ) && count( $taxonomies ) > 0 ) {
			foreach ( $taxonomies as $key => $taxonomy ) {
				$taxonomy_obj_a[] = get_taxonomy( $taxonomy );
			}
		}

		echo wp_json_encode( $taxonomy_obj_a );
		die();
	}

	/**
	 * Get the list of terms associated with the provided taxonomy.
	 */
	public function daim_get_terms() {

		// check the referer.
		if ( ! check_ajax_referer( 'daim', 'security', false ) ) {
			esc_html_e( 'Invalid AJAX Request', 'deextamp' );
			die();
		}

		// check the capability.
		if ( ! current_user_can( get_option( $this->shared->get( 'slug' ) . '_term_groups_menu_required_capability' ) ) ) {
			esc_html_e( 'Invalid Capability', 'interlinks-manager');
			die();
		}

		// get the data.
		$taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_key( $_POST['taxonomy'] ) : null;

		$terms = get_terms(
			array(
				'hide_empty' => 0,
				'orderby'    => 'term_id',
				'order'      => 'DESC',
				'taxonomy'   => $taxonomy,
			)
		);

		if ( is_object( $terms ) && get_class( $terms ) === 'WP_Error' ) {
			return '0';
		} else {
			echo wp_json_encode( $terms );
		}

		die();
	}
}