'; protected $highlight_end_tag = ''; protected $emphasis_start_tag = ''; protected $emphasis_end_tag = ''; protected $end_of_line = '
'; protected $ellipses_sequence = '…'; protected $max_meta_value_length = 50; protected $js_infused_links_allowed = true; protected $supports_hyperlinks = true; /** * List of tags compatible with function strip_tags before PHP 7.4 (must be string, not an array). * * @var string */ protected $tags_allowed_in_message = '
'; /** * @var bool */ protected $supports_metadata = true; public function __construct( $plugin ) { $this->_plugin = $plugin; } public function get_end_of_line() { return $this->end_of_line; } /** * @param $expression * @param $value * @param null $occurrence_id * * @return false|mixed|string|void|WP_Error * @throws Freemius_Exception * * @since 4.2.1 */ public function format_meta_expression( $expression, $value, $occurrence_id = null, $metadata = [] ) { switch ( true ) { case '%Message%' == $expression: return esc_html( $value ); case '%MetaLink%' == $expression: if ( $this->js_infused_links_allowed ) { $label = __( 'Exclude Custom Field from the Monitoring', 'wp-security-audit-log' ); return " {$label}"; } return ''; case in_array( $expression, array( '%MetaValue%', '%MetaValueOld%', '%MetaValueNew%' ) ): // trim the meta value to the maximum length and append configured ellipses sequence $result = strlen( $value ) > $this->max_meta_value_length ? ( substr( $value, 0, 50 ) . $this->ellipses_sequence ) : $value; return $this->wrap_in_hightlight_markup( esc_html( $result ) ); case '%ClientIP%' == $expression: case '%IPAddress%' == $expression: if ( is_string( $value ) ) { $sanitized_ips = str_replace( array( '"', '[', ']' ), '', $value ); return $this->wrap_in_hightlight_markup( $sanitized_ips ); } else { return $this->wrap_in_emphasis_markup( __( 'unknown', 'wp-security-audit-log' ) ); } case '%PostUrlIfPlublished%' === $expression: $post_id = null; if ( $occurrence_id === 0 && is_array( $metadata ) && array_key_exists( 'PostID', $metadata ) ) { $post_id = $metadata['PostID']; } else { $post_id = $this->get_occurrence_meta_item( $occurrence_id, 'PostID' ); } $occ_post = $post_id !== null ? get_post( $post_id ) : null; if ( null !== $occ_post && 'publish' === $occ_post->post_status ) { return get_permalink( $occ_post->ID ); } return ''; case '%MenuUrl%' === $expression: $menu_id = null; if ( $occurrence_id === 0 && is_array( $metadata ) && array_key_exists( 'MenuID', $metadata ) ) { $menu_id = $metadata['MenuID']; } else { $menu_id = $this->get_occurrence_meta_item( $occurrence_id, 'MenuID' ); } if ( null !== $menu_id ) { return add_query_arg( array( 'action' => 'edit', 'menu' => $menu_id, ), admin_url( 'nav-menus.php' ) ); } return ''; case '%Attempts%' === $expression: // Failed login attempts. $check_value = (int) $value; if ( 0 === $check_value ) { return ''; } else { return $value; } case '%LogFileText%' === $expression: // Failed login file text. if ( $this->js_infused_links_allowed ) { return '' . esc_html__( 'Download the log file.', 'wp-security-audit-log' ) . ''; } return ''; case in_array( $expression, array( '%PostStatus%', '%ProductStatus%' ), true ): $result = ( ! empty( $value ) && 'publish' === $value ) ? __( 'published', 'wp-security-audit-log' ) : $value; return $this->wrap_in_hightlight_markup( esc_html( $result ) ); case '%multisite_text%' === $expression: if ( $this->_plugin->IsMultisite() && $value ) { $site_info = get_blog_details( $value, true ); if ( $site_info ) { $site_url = $site_info->siteurl; return ' on site ' . $this->wrap_in_hightlight_markup( $this->format_link( $expression, $site_info->blogname, $site_url ) ); } } return ''; case '%ReportText%' === $expression: case '%ChangeText%' === $expression: return ''; case '%TableNames%' === $expression: $value = str_replace( ',', ', ', $value ); return $this->wrap_in_hightlight_markup( esc_html( $value ) ); case '%LineBreak%' === $expression: return $this->end_of_line; case '%PluginFile%' === $expression: return $this->wrap_in_hightlight_markup( dirname( $value ) ); default: // if we didn't get a match already try get one via a filter. return apply_filters( 'wsal_meta_formatter_custom_formatter', $value, $expression ); } } /** * Wraps given value in highlight markup. * * For example meta values displayed as {meta value} in the WP admin UI. * * @param string $value * * @return string */ public function wrap_in_hightlight_markup( $value ) { return $this->highlight_start_tag . $value . $this->highlight_end_tag; } /** * Wraps given value in emphasis markup. * * For example an unknown IP address is displayed as unknown in the WP admin UI. * * @param string $value * * @return string */ public function wrap_in_emphasis_markup( $value ) { return $this->emphasis_start_tag . $value . $this->emphasis_end_tag; } /** * Handles formatting of hyperlinks in the event messages. * * Contains: * - check for empty values * - check if the link is disabled * - optional URL processing * * @param string $url * @param string $label * @param string $title * @param string $target * * @return string * @see process_url()) * */ public final function format_link( $url, $label, $title = '', $target = '_blank' ) { // check for empty values if ( null === $url || empty( $url ) ) { return ''; } $processed_url = $this->process_url( $url ); return $this->build_link_markup( $processed_url, $label, $title, $target ); } /** * Override this method to process the raw URL value in a subclass. * * An example would be URL shortening or adding tracking params to all or selected URL. * * Default implementation returns URL as is. * * @param string $url * * @return string */ protected function process_url( $url ) { return $url; } /** * Override this method in subclass to format hyperlinks differently. * * Default implementation returns HTML A tag. * * @param string $url * @param string $label * @param string $title * @param string $target * * @return string */ protected function build_link_markup( $url, $label, $title = '', $target = '_blank' ) { $title = empty( $title ) ? $label : $title; return '' . $label . ''; } /** * @return bool True if the formatter supports hyperlinks as part of the alert message. */ public function supports_hyperlinks() { return $this->supports_hyperlinks; } /** * @return bool True if the formatter supports metadata as part of the alert message. */ public function supports_metadata() { return $this->supports_metadata; } /** * Message for some events contains HTML tags for highlighting certain parts of the message. * * This function replaces the original HTML tags with the correct highlight tags. * * It also strips any additional HTML tags apart from hyperlink and an end of line to support legacy messages. * * @param string $message * * @return string */ public function process_html_tags_in_message( $message ) { $result = preg_replace( [ '//', '/<\/strong>/' ], [ $this->highlight_start_tag, $this->highlight_end_tag ], $message ); return strip_tags( $result, $this->tags_allowed_in_message ); } /** * Helper function to get meta value from an occurrence. * * @param int $occurrence_id * @param string $meta_key * * @return mixed|null Meta value if exists. Otherwise null * @since 4.2.1 */ private function get_occurrence_meta_item( $occurrence_id, $meta_key ) { // get connection. $db_config = WSAL_Connector_ConnectorFactory::GetConfig(); // Get DB connector configuration. $connector = $this->_plugin->getConnector( $db_config ); // Get connector for DB. $wsal_db = $connector->getConnection(); // Get DB connection. // get values needed. $meta_adapter = new WSAL_Adapters_MySQL_Meta( $wsal_db ); $meta_result = $meta_adapter->LoadByNameAndOccurrenceId( $meta_key, $occurrence_id ); return isset( $meta_result['value'] ) ? $meta_result['value'] : null; } }