HEX
Server: Apache
System: Linux srv-plesk28.ps.kz 5.14.0-284.18.1.el9_2.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Jun 29 17:06:27 EDT 2023 x86_64
User: greencl1 (10085)
PHP: 8.1.33
Disabled: apache_setenv,dl,eval,exec,openlog,passthru,pcntl_exec,pcntl_fork,popen,posix_getpwuid,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,socket_create,socket_create_listen,socket_create_pair,syslog,system,socket_listen,stream_socket_server
Upload Files
File: /var/www/vhosts/greenclinic.kz/newsite/wp-content/plugins/cf7-telegram/classes/wpcf7telegram.php
<?php
class wpcf7_Telegram{
	
	private
	$cmd = 'cf7tg_start',	
	$bot_token;
	
	static
	$instance;
	
	public 
	$domain = 'cf7-telegram',
	$api_url = 'https://api.telegram.org/bot%s/',
	$chats = array(),
	$addons = array(),
	$markdown_tags = array(
		'bold' => array(
			'<h1>','</h1>', '<h2>','</h2>', '<h3>','</h3>', '<h4>','</h4>', '<h5>','</h5>', '<h6>','</h6>',
			'<b>','</b>',
			'<strong>','</strong>',
			'<mark>','</mark>'
		),
		'italic' => array(
			'<em>','</em>',
			'<i>','</i>'
		),
		'code' => array(
			'<code>','</code>',
			'<pre>','</pre>'
		),
		'underline'	=> array(
			'<u>','</u>', '<ins>','</ins>',
		),
		'strike' => array(
			'<s>','</s>', '<strike>','</strike>',
		),
	);
	
	function __construct(){
		if ( ! empty( self::$instance ) ) return new WP_Error( 'duplicate_object', __( 'Prevent duplicate object creation', WPCF7TG_DOMAIN ) );
	}
	
	private function init(){
		$this->addons = array(
			'wpcf7tg_mediafiles' => __( 'File Sending', WPCF7TG_DOMAIN ),
		);
		
		$this->load_bot_token();
		$this->load_chats();
		
		add_action( 'admin_menu', array( $this, 'menu_page' ) );
		add_action( 'admin_init', array( $this, 'save_form' ), 50 );
		add_action( 'admin_init', array( $this, 'settings_section' ), 999 );
		add_action( 'current_screen', array( $this, 'current_screen' ), 999 );
		add_action( 'wpcf7_telegram_settings', array( $this, 'check_updates' ), 999 );
		add_action( 'wpcf7_init', array( $this, 'tg_shortcode' ) );
		add_action( 'wpcf7_before_send_mail', array( $this, 'send' ), 99999, 3 );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'wp_ajax_wpcf7_tg', array( $this, 'ajax' ) );	
	}
	
	public static function get_instance(){
		if ( empty( self::$instance ) ) :
			self::$instance = new self;
			self::$instance->init();
		endif;

		return self::$instance;
	}
	
	public function current_screen(){
		$screen = get_current_screen();
		//if ( 'contact-form-7_page_wpcf7_tg' != $screen->id ) return;
		if ( false === strpos( $screen->id, 'wpcf7_tg' ) ) return;
		do_action( 'wpcf7_telegram_settings' );
	}
	
	public function plugin_url() {
		return untrailingslashit( plugins_url( '/', WPCF7TG_FILE ) );
	}
	
	function admin_enqueue_scripts(){
		$me = self::get_instance();
		if ( ! did_action( 'wpcf7_telegram_settings' ) ) return;
		wp_enqueue_style( 'wpcf7telegram-admin-styles', $me->plugin_url() . '/css/admin.css', null, WPCF7TG_VERSION );
		wp_enqueue_script( 'wpcf7telegram-admin', $me->plugin_url() . '/js/admin.js', null, WPCF7TG_VERSION );
		wp_localize_script( 'wpcf7telegram-admin', 'wpData', array(
			'ajax'		=> admin_url('admin-ajax.php'),
			'nonce'		=> wp_create_nonce( 'wpcf7_telegram_nonce' ),
			'l10n'		=> array(
				'confirm_approve'	=> __( 'Do you really want to approve?', WPCF7TG_DOMAIN ),
				'confirm_refuse'	=> __( 'Do you really want to refuse?', WPCF7TG_DOMAIN ),
				'confirm_pause'		=> __( 'Do you really want to pause?', WPCF7TG_DOMAIN ),
				'approved'	=> __( 'Successfully approved', WPCF7TG_DOMAIN ),
				'refused'	=> __( 'Request refused', WPCF7TG_DOMAIN ),
			),
		) );
	}

	function settings_section() {
		$me = self::get_instance();
		add_settings_section(
			'wpcf7_tg_sections__main', 
			__( 'Bot-settings', WPCF7TG_DOMAIN ),
			array( $me, 'sections__main_callback_function' ),
			'wpcf7tg_settings_page'
		);
		
		add_settings_field( 
			'bot_token', 
			__( 'Bot Token<br/><small>You need to create your own Telegram-Bot.<br/><a target="_blanc" href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">How to create</a></small>', WPCF7TG_DOMAIN ), 
			array( $me, 'settings_clb' ), 
			'wpcf7tg_settings_page', 
			'wpcf7_tg_sections__main', 
			array(
				'type'		=> 'password',
				'name'		=> 'wpcf7_telegram_tkn',
				'value'		=> self::has_token_constant() ? '' : $me->get_bot_token(),
				'disabled'	=> self::has_token_constant(),
				'ph'		=> self::has_token_constant() ? __( 'Defined by WPFC7TG_BOT_TOKEN constant', WPCF7TG_DOMAIN ) : __( 'or define by WPFC7TG_BOT_TOKEN constant', WPCF7TG_DOMAIN ),
			)
		);
	}
	
	function settings_clb( $data ){
		switch ( $data['type'] ){
			case 'text' :;
			case 'password' :
				$disabled = ! empty( $data['disabled'] ) ? ' disabled="disabled" ' : '';
				$placeholder = ' placeholder="'. esc_attr( @$data['ph'] ) . '"';
				echo 
				'<input type="'. esc_attr( $data['type'] ) .'" ' .
					'name="'. esc_attr( $data['name'] ) .'" ' .
					'value="'. esc_attr( $data['value'] ) .'"' .
					'class="large-text" ' .
					$disabled .
					$placeholder .
				'/>'; break;
		}
	}
	
	function menu_page(){
		add_submenu_page( 'wpcf7', 'CF7 Telegram', 'CF7 Telegram', 'wpcf7_read_contact_forms', 'wpcf7_tg', array( self::get_instance(), 'plugin_menu_cbf' ) );
	}
	function plugin_menu_cbf(){
	?>	
		<div class="wrap">	
			<h1><?php echo __( 'Telegram notificator settings', WPCF7TG_DOMAIN ); ?></h1>
			<?php 
				$this->bot_status();
				$this->view_full_list();
				settings_errors(); 
			?>
			<form method="post" action="admin.php?page=wpcf7_tg"> 
				<?php settings_fields( 'wpcf7tg_settings_page' ); ?>	
				<?php do_settings_sections( 'wpcf7tg_settings_page' ); ?> 
				<input type="hidden" name="wpcf7tg_settings_form_action" value="save" />
				<p><?php echo __( 'Just use the shortcode <code>[telegram]</code> in the form for activate notification through Telegram.', WPCF7TG_DOMAIN ); ?></p>
				<?php submit_button(); ?>	
			</form>	
			<?php
				$this->view_addonds();
			?>
		</div> 
	<?php			
	}
	
	function sections__main_callback_function(){
		echo '';
	}
	
	function tg_shortcode(){
		wpcf7_add_form_tag( 'telegram', array( self::get_instance(), 'tg_shortcode_handler' ) );
	}
	function tg_shortcode_handler(){
		return '<input type="hidden" name="wpcf7tg_sending" value="1" />';
	}
	
	function save_form(){
		$me = self::get_instance();
		if ( $me->current_action() !== 'update' ) return;
		if ( ! wp_verify_nonce( @ $_POST['_wpnonce'], 'wpcf7tg_settings_page-options' ) ) return;
		
		$me->save_bot_token();
	}
	
	function current_action(){
		return isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
	}
	
	private function load_bot_token(){
		$token = get_option( 'wpcf7_telegram_tkn' );
		$this->bot_token = empty( $token ) ? '' : $token;
		
		return $this;
	}
	
	private function set_bot_token( $token ){
		$this->bot_token = $token;
		update_option( 'wpcf7_telegram_tkn', $token, false );
		return $this;
	}
	
	private function save_bot_token(){
		if ( self::has_token_constant() ) :
			$this->set_bot_token( '' );
			return;
		endif;
		
		$token = $_REQUEST['wpcf7_telegram_tkn'];
		$this->set_bot_token( $token );
		return $this;
	}
	
	private function save_chats( $chats ){
		update_option( 'wpcf7_telegram_chats', $chats, false );
		return $this;
	}
	
	function load_chats(){
		$chats = get_option( 'wpcf7_telegram_chats' );
		#	Back-compat
		if ( ! empty( $chats ) && is_string( $chats ) ) :
			$list = explode( ',', $chats );
			$chats = array();
			
			foreach( $list as $item )
			$chats[ $item ] = array( 'id' => $item, 'status' => 'active', 'first_name' => '', 'last_name' => '' );
			
			$this->save_chats( $chats );
		endif;
		$this->chats = empty( $chats ) ? array() : ( array ) $chats;
		return $this;
	}
	
	private function get_bot_token(){
		return $this->bot_token;
	}		

	private function get_api_url(){
		$token = self::has_token_constant() ? WPFC7TG_BOT_TOKEN : $this->get_bot_token();
		return sprintf( $this->api_url, $token );
	}
	
	function markdown( $content ){
		$tags = apply_filters( 'wpcf7tg_markdown', $this->markdown_tags );
		extract( $tags );
		$content = ! empty( $bold ) ? str_replace( $bold, '*', $content ) : $content;
		$content = ! empty( $italic ) ? str_replace( $italic, '_', $content ) : $content;
		$content = ! empty( $code ) ? str_replace( $code, '`', $content ) : $content;
		$content = ! empty( $underline ) ? str_replace( $underline, '__', $content ) : $content;
		$content = ! empty( $strike ) ? str_replace( $strike, '~', $content ) : $content;
		
		return $content;
	}
	
	function send( $cf, & $abort, $instance ){
		$me = self::get_instance();
		$list = $me->get_chats();
		if ( empty( $list ) ) return;
		
		$data = $instance->get_posted_data();
		
		if ( empty( $data['wpcf7_telegram'] ) && empty( $data['wpcf7tg_sending'] ) ) return; /* Backword compat 'wpcf7_telegram'. To delete since 1.0 */
		if ( $abort ) return;
		if ( apply_filters( 'wpcf7tg_skip_tg', false, $cf, $instance ) ) return;

		$mail = $cf->prop( 'mail' );
		$output = wpcf7_mail_replace_tags( @ $mail[ 'body' ] );
		$mode = 'HTML';
		if ( false === @ $mail['use_html'] ) :
			$mode = 'Markdown';
			$output = $me->markdown( $output ); 			
			$output = wp_kses( $output, array() );
		else :
			$output = wp_kses( $output, array(
				'a'	=> array( 'href' => true ),
				'b' => array(), 'strong' => array(), 'i' => array(), 'em' => array(), 'u' => array(), 'ins' => array(), 's' => array(), 'strike' => array(), 'del' => array(), 'code' => array(), 'pre' => array(),
			) );
		endif;		
		
		foreach( $list as $id => $chat ) :
			$chat_id = is_numeric( $id ) ? $id : $chat['id'];
			if ( ! is_numeric( $chat_id ) ) continue;			
			$msg_data = array(
				'chat_id'					=> $chat_id,
				'text'						=> $output,
				'parse_mode'				=> $mode,
				'disable_web_page_preview'	=> true
			);
			$me->api_request( 'sendMessage', apply_filters( 'wpcf7tg_sendMessage', $msg_data, $chat_id, $mode ) );
			do_action( 'wpcf7tg_message_sent', $msg_data, $instance );
		endforeach;
		
		do_action( 'wpcf7tg_messages_sent', $list, $output, $mode, $instance );
	}
	
	function check_bot(){
		$check = $this->api_request( 'getMe' );
		
		if ( false === $check ) 
		return new WP_Error( 'check_bot_error', __( 'An error has occured. See php error log.', WPCF7TG_DOMAIN ) );

		return $check;		
	}
	
	private function bot_status(){
		if ( ! $this->has_token() ) return;
		$check_bot = $this->check_bot();
		$status_format = 
			'<div class="check_bot %s">
				<strong class="status">%s</strong>
				<div>'. __( 'Bot username', WPCF7TG_DOMAIN ) . ': <code class="bot_username">%s</code></div>
			</div>';
		
		if ( ! is_wp_error( $check_bot ) ) :
			echo ( true === @ $check_bot->ok ) ? 
				sprintf( $status_format, 'online', __( 'Bot is online', WPCF7TG_DOMAIN ), '@' . $check_bot->result->username ) :
				sprintf( $status_format, 'failed', __( 'Bot is broken', WPCF7TG_DOMAIN ), __( 'unknown', WPCF7TG_DOMAIN ) );
		else :
			echo $check_bot->get_error_message();
		endif;
	}
	
	private function view_full_list(){
		echo '<h2>'. __( 'Subscribers list', WPCF7TG_DOMAIN ) .'</h2>';
		
		$req = $this->pending_html_list();
		$app = $this->approved_html_list();
		
		if ( ! $req && ! $app ) _e( 'List is empty', WPCF7TG_DOMAIN );
		
		echo '<p>', sprintf( __( 'Add user: send the <code>%s</code> comand to your bot', WPCF7TG_DOMAIN ), '/'. $this->cmd ), '</p>';
		echo '<p>', sprintf( __( 'Add group: add your bot to the group and send the <code>%s</code> comand to your group', WPCF7TG_DOMAIN ), '/'. $this->cmd ), '</p>';
	}
	
	private function get_listitem_data( $chat, $status = 'pending' ){
		return array( 
			$status,
			$chat['id'],
			$chat['id'] > 0 ? 'admin-users' : 'groups',
			empty( $str = trim( $chat['id'] > 0 ?
				$chat['first_name'] .' '. $chat['last_name'] :
				$chat['title'] ) ) ? "[{$chat['id']}]" : $str,
			empty( $chat['username'] ) ? '' : '@'. $chat['username'],
			isset( $chat['date'] ) ? wp_date( 'j F Y H:i:s', $chat['date'] ) : '',
		);
	}
	
	private function get_chats( $status = 'active' ){
		$result = array();
		foreach ( $this->chats as $id => $chat ) :
			if ( $status == $chat['status'] )
			$result[ $id ] = $chat;
		endforeach;
		
		return $result;
	}
	
	private function approved_html_list(){
		$list = $this->get_chats();
		if ( empty( $list) ) return array();
		
		foreach( $list as $id => $chat )				
		echo vsprintf( $this->get_template( 'f_item' ), $this->get_listitem_data( $chat, 'active' ) );

		return true;
	}
	
	private function pending_html_list(){
		$data = $this->get_chats( 'pending' );
		if ( empty( $data ) ) return false;
		
		foreach( $data as $id => $item ) :
			echo vsprintf( $this->get_template( 'f_item' ), $this->get_listitem_data( $item ) );
		endforeach;
		
		return true;
	}
	
	function check_updates(){
		$me = self::get_instance();
		$update_id = get_option( 'wpcf7_telegram_last_update_id' );
		$param = array(
			'allowed_updates'	=> array( 'message' ),
			'offset'			=> $update_id,
		);
		$updates = $me->api_request( 'getUpdates', $param );		
		if ( empty( $updates->result ) ) return;		
		
		$update_ids = array();		
		$upd = array();
		
		foreach( $updates->result as $one ) :
			$update_ids []= $one->update_id;
			
			if ( is_array( @ $one->message->entities ) )
			foreach( $one->message->entities as $ent ) :
				$cmd = substr( $one->message->text, $ent->offset, $ent->length );
				if ( 'bot_command' == $ent->type && '/' . $me->cmd === $cmd && empty( $me->chats[ $one->message->chat->id ] ) ) :
					$upd[ $one->message->chat->id ] = ( array ) $one->message->chat;
					$upd[ $one->message->chat->id ]['date'] = $one->message->date;
					$upd[ $one->message->chat->id ]['status'] = 'pending';
				endif;
			endforeach;
		
			if ( false === strpos( $one->message->text, 'cf7_start' ) ) continue;

		endforeach;
		
		$me->chats += $upd;
		$me->save_chats( $me->chats );

		sort( $update_ids, SORT_NUMERIC );
		$next_update = array_pop( $update_ids );
		update_option( 'wpcf7_telegram_last_update_id', ( int ) $next_update + 1 );

	}
	
	private function action_approve( $chat_id, & $new_status ){
		$new_status = 'active';
		if ( empty( $this->chats[ $chat_id ] ) ) return false;
		$this->chats[ $chat_id ]['status'] = $new_status;
		$this->save_chats( $this->chats );
		
		$this->api_request( 'sendMessage', array(
			'chat_id'					=> $chat_id,
			'text'						=> __( 'Subscribed for Contact Form 7 notifications from', WPCF7TG_DOMAIN ) . ' ' . home_url(),
			'disable_web_page_preview'	=> true,
		) );
		
		return true;
	}
	
	private function action_pause( $id, & $new_status ){
		$new_status = 'pending';
		if ( empty( $this->chats[ $id ] ) ) return false;
		$this->chats[ $id ]['status'] = $new_status;
		$this->save_chats( $this->chats );
		
		return true;
	}
	
	private function action_refuse( $id, & $new_status ){
		$new_status = 'deleted';
		unset( $this->chats[ $id ] );
		$this->save_chats( $this->chats );
		
		return true;
	}

	public function api_request( $method, $parameters = null, $headers = null ) {
		if ( ! is_string( $method ) ) :
			error_log( "[TELEGRAM] Method name must be a string\n" );
			return false;
		endif;

		if ( is_null( $parameters ) ):
			$parameters = array();
		endif;

		$url = $this->get_api_url() . $method;
		$args = array(
			'timeout'		=> 5,
			'redirection'	=> 5,
			'blocking'		=> true,
			'method'		=> 'POST',
			'body'			=> $parameters,
		);
		
		if ( ! empty( $headers ) )
		$args['headers'] = $headers;
		
		return $this->request( $url, $args );
	}

	private function request( $url, $args ) {
		$response = wp_remote_post( $url, $args );
		if ( is_wp_error( $response ) ) :
			error_log( "wp_remote_post returned error : ". $response->get_error_code() . ': ' . $response->get_error_message() . ' : ' . $response->get_error_data() ."\n");
			return false;
		endif;
		$http_code = intval( $response['response']['code'] );
		if ( $http_code >= 500 ) :
			// do not to DDOS server if something goes wrong
			error_log( "[TELEGRAM] Server return status {$http_code}" ."\n" );
			sleep( 3 );
			return false;
		elseif ( $http_code == 401 ) :
			//throw new Exception( 'Invalid access token provided' );
			error_log( "[TELEGRAM] Wrong token \n" );
			return json_decode( $response['body'] );
		elseif ( $http_code != 200 ) :
			error_log( "[TELEGRAM] Request has failed with error {$response['response']['code']}: {$response['response']['message']}\n" );
			return false;
		elseif ( empty( $response['body'] ) ) :
			error_log( "[TELEGRAM] Server return empty body" );
			return false;
		else :
			return json_decode( $response['body'] );
		endif;
	}
	
	public function has_token_constant(){
		return defined( 'WPFC7TG_BOT_TOKEN' );
	}
	
	private function has_token(){
		return ( $this->has_token_constant() || $this->get_bot_token() ) ;
	}
	
	private function get_template( $name ){
		$t['f_item'] =
		'<div class="wpcf7tg_notice notice-%1$s is-dismissible" data-chat="%2$d" status="%1$s" >
			<div class="info dashicons-before dashicons-%3$s">
				<span class="username">
					%4$s
				</span>
				<span class="nickname">
					%5$s
				</span>
				%6$s
			</div>
			<div class="buttons">
				<a class="approve" data-action="approve" ><span class="screen-reader-text">'. __( 'Approve', WPCF7TG_DOMAIN ) . '</span>'. __( 'Approve', WPCF7TG_DOMAIN ) . '</a>
				<a class="pause" data-action="pause" ><span class="screen-reader-text">'. __( 'Pause', WPCF7TG_DOMAIN ) . '</span>'. __( 'Pause', WPCF7TG_DOMAIN ) . '</a>
				<a class="refuse" data-action="refuse" ><span class="screen-reader-text">'. __( 'Delete', WPCF7TG_DOMAIN ) . '</span>'. __( 'Delete', WPCF7TG_DOMAIN ) . '</a>
			</div>
		</div>';
		
		return $t[ $name ];
	}
	
	function ajax(){
		$me = self::get_instance();
		check_ajax_referer( 'wpcf7_telegram_nonce' );
		$chat_id = @ $_POST['chat'];
		if ( empty( $chat_id ) ) wp_die( json_encode( new \WP_Error( 'empty_chat_id', 'There is no chat_id in request', array( 'status' => 400 ) ) ) );
		
		$action = 'action_' . @ $_POST['do_action'];
		if ( ! method_exists( $me, $action ) ) wp_die( json_encode( new \WP_Error( 'wrong_action', 'There is no correct action in request', array( 'status' => 400 ) ) ) );
		
		$new_status = '';
		echo json_encode( array( 'result' => $me->$action( $chat_id, $new_status ), 'chat' => $chat_id, 'new_status' => $new_status ) );
		wp_die();
	}
	
	function view_addonds(){
		echo '<h2>'. __( 'Extensions', 'cf7-telegram' ) .'</h2>';
		
		foreach ( $this->addons as $slug => $name ) :
			$attachment_addon_link = "https://nebster.net/product/contact-form-7-telegram-attachments/";
			echo class_exists( $slug ) ?
				'<p>' . __( 'Uses addon:', WPCF7TG_DOMAIN ) . ' ' . $name . '</p>' :
				/* translators: 1. File sending extension link, 2. end sale date, 3. "Get it now!" link  */
				sprintf( __( 'We have a %1$s available that is 75%% OFF until %2$s: %3$s', WPCF7TG_DOMAIN ),
					'<a href="'.$attachment_addon_link.'" target="_blank" >' . __( 'File sending extension', WPCF7TG_DOMAIN ) . '</a>',
					date_i18n( get_option( 'date_format' ), strtotime( '31-12-' . date( 'Y' ) )  ),
					'<a href="'.$attachment_addon_link.'" target="_blank" >' . __( 'Get it now!', WPCF7TG_DOMAIN ) . '</a>',
				) . '</p>';
		endforeach;
	}
}