HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: /var/www/html/triad-infosec/wp-content/plugins/simple-history/inc/class-export.php
<?php

namespace Simple_History;

/**
 * Class to contain logic for exporting events.
 *
 * Used by core export module and export searched events feature in premium plugin.
 */
class Export {
	/** @var array $query_args Query arguments. Will be passed to log query class. */
	protected $query_args = [];

	/** @var string $format Export format. "json", "csv", or "html".  */
	protected $format = 'json';

	/** @var Simple_History $simple_history Simple History instance. */
	protected $simple_history;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->simple_history = Simple_History::get_instance();
	}

	/**
	 * Set the query arguments.
	 *
	 * @param array $args Query arguments.
	 * @return self Chainable method.
	 */
	public function set_query_args( $args ) {
		$this->query_args = $args;

		return $this;
	}

	/**
	 * Set the export format.
	 *
	 * @param string $format Export format. "csv", "json", or "html.
	 * @return self Chainable method.
	 */
	public function set_download_format( $format ) {
		$this->format = $format;

		return $this;
	}

	/**
	 * Add hooks that modify the output of the events.
	 */
	protected function add_hooks() {
		// Disable relative time output in header.
		add_filter( 'simple_history/header_time_ago_max_time', '__return_zero' );
		add_filter( 'simple_history/header_just_now_max_time', '__return_zero' );

		// Don't use "You" if event is initiated by the same user that does the export.
		add_filter( 'simple_history/header_initiator_use_you', '__return_false' );
	}

	/**
	 * Download events that match query args.
	 *
	 * Events are fetched in batches, with each batch being output to the export file.
	 *
	 * The export file is output to the browser and then the script exits.
	 *
	 * @return never
	 */
	public function download() {
		$this->add_hooks();

		$export_format = $this->format;

		$query = new Log_Query();

		$download_query_args = $this->query_args;

		$query_result = $query->query( $download_query_args );

		$pages_count = $query_result['pages_count'];
		$page_current = $query_result['page_current'];

		$fp = fopen( 'php://output', 'w' );

		$attachment_header_template = 'Content-Disposition: attachment; filename="%1$s"';

		if ( 'csv' == $export_format ) {
			$filename = 'simple-history-export-' . time() . '.csv';
			header( 'Content-Type: text/plain' );
			header( sprintf( $attachment_header_template, $filename ) );
		} elseif ( 'json' == $export_format ) {
			$filename = 'simple-history-export-' . time() . '.json';
			header( 'Content-Type: application/json' );
			header( sprintf( $attachment_header_template, $filename ) );
		} elseif ( 'html' == $export_format ) {
			$filename = 'simple-history-export-' . time() . '.html';
			header( 'Content-Type: text/html' );
			header( sprintf( $attachment_header_template, $filename ) );
		}

		// Some formats need to output some stuff before the actual loops.
		if ( 'json' == $export_format ) {
			$json_row = '[';
			fwrite( $fp, $json_row );
		} elseif ( 'html' == $export_format ) {
			$html = sprintf(
				'
			<!doctype html>
			<meta charset="utf-8">
			<title>Simple History export</title>
			<ul>
			'
			);
			fwrite( $fp, $html );
		}

		// Paginate through all pages and all their rows.
		$row_loop = 0;
		while ( $page_current <= $pages_count + 1 ) {

			foreach ( $query_result['log_rows'] as $one_row ) {

				set_time_limit( 30 );

				if ( 'csv' == $export_format ) {
					$this->output_csv_row( $fp, $one_row );
				} elseif ( 'json' == $export_format ) {
					$this->output_json_row( $fp, $one_row, $row_loop );
				} elseif ( 'html' == $export_format ) {
					$this->output_html_row( $fp, $one_row );
				}

				$row_loop++;
			}

			flush();

			// Fetch next page.
			$page_current++;
			$download_query_args['paged'] = $page_current;
			$query_result = $query->query( $download_query_args );
		}

		if ( 'json' == $export_format ) {
			$json_row = ']';
			fwrite( $fp, $json_row );
		} elseif ( 'html' == $export_format ) {
			$html = sprintf( '</ul>' );
			fwrite( $fp, $html );
		}

		fclose( $fp );
		flush();

		exit;
	}

	/**
	 * Output a CSV row.
	 *
	 * @param resource $fp File pointer.
	 * @param object   $one_row Log row.
	 */
	protected function output_csv_row( $fp, $one_row ) {
		$header_output = strip_tags( html_entity_decode( $this->simple_history->get_log_row_header_output( $one_row ), ENT_QUOTES, 'UTF-8' ) );
		$header_output = trim( preg_replace( '/\s\s+/', ' ', $header_output ) );

		$message_output = strip_tags( html_entity_decode( $this->simple_history->get_log_row_plain_text_output( $one_row ), ENT_QUOTES, 'UTF-8' ) );

		$user_email = empty( $one_row->context['_user_email'] ) ? null : $one_row->context['_user_email'];
		$user_login = empty( $one_row->context['_user_login'] ) ? null : $one_row->context['_user_login'];
		$user_roles = [];

		if ( $user_email ) {
			$user = get_user_by( 'email', $user_email );
			$user_roles = $user->roles ?? array();
		}

		$user_roles_comma_separated = implode( ', ', $user_roles );

		$date_local = wp_date( 'Y-m-d H:i:s', strtotime( $one_row->date ) );

		fputcsv(
			$fp,
			array(
				Helpers::esc_csv_field( $one_row->date ),
				Helpers::esc_csv_field( $date_local ),
				Helpers::esc_csv_field( $one_row->logger ),
				Helpers::esc_csv_field( $one_row->level ),
				Helpers::esc_csv_field( $one_row->initiator ),
				Helpers::esc_csv_field( $one_row->context_message_key ),
				Helpers::esc_csv_field( $user_email ),
				Helpers::esc_csv_field( $user_login ),
				Helpers::esc_csv_field( $user_roles_comma_separated ),
				Helpers::esc_csv_field( $header_output ),
				Helpers::esc_csv_field( $message_output ),
				// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
				Helpers::esc_csv_field( $one_row->subsequentOccasions ),
			)
		);
	}

	/**
	 * Output a JSON row.
	 *
	 * @param resource $fp File pointer.
	 * @param object   $one_row Log row.
	 * @param int      $row_loop Row loop counter.
	 */
	protected function output_json_row( $fp, $one_row, $row_loop ) {
		$comma = $row_loop == 0 ? "\n" : ",\n";
		$json_row = $comma . Helpers::json_encode( $one_row );
		fwrite( $fp, $json_row );
	}

	/**
	 * Output an HTML row.
	 *
	 * @param resource $fp File pointer.
	 * @param object   $one_row Log row.
	 */
	protected function output_html_row( $fp, $one_row ) {
		$html = sprintf(
			'
			<li>
				<div>%1$s</div>
				<div>%2$s</div>
				<div>%3$s</div>
			</li>
			',
			$this->simple_history->get_log_row_header_output( $one_row ),
			$this->simple_history->get_log_row_plain_text_output( $one_row ),
			$this->simple_history->get_log_row_details_output( $one_row )
		);

		fwrite( $fp, $html );
	}
}