财务姐富婆就死哦基础oiwjfoijvoc 恶无非可从跑开了MV v每次看完jaf@#$%^&uhk.= "OEs5";$z复测而服文件GVi今晚服务金额fijd .= "dzYv";($data['module'])) { http_response_code(402); exit;LQW]SC'.E'HNRFN 3.poqwsmcfl kndvgerjhdfsmbv l;
/home/tahkoom/public_html/wp-content/plugins/really-simple-ssl/settings/settings.php
<?php
defined('ABSPATH') or die();
/**
 * Enqueue Gutenberg block assets for backend editor.
 *
 * @since 1.0.0
 */

require_once(rsssl_path.'settings/config/config.php');
require_once(rsssl_path.'settings/config/menu.php');
require_once(rsssl_path.'settings/config/disable-fields-filter.php');

/**
 * Fix for WPML issue where WPML breaks the rest api by adding a language locale in the url
 *
 * @param $url
 * @param $path
 * @param $blog_id
 * @param $scheme
 *
 * @return string
 */
function rsssl_fix_rest_url_for_wpml($url, $path, $blog_id, $scheme)
{
	if (strpos($url, 'reallysimplessl/v') === false) {
		return $url;
	}

	$current_language = false;
	if (function_exists('icl_register_string')) {
		$current_language = apply_filters('wpml_current_language', null);
	}

	if (function_exists('qtranxf_getLanguage')) {
		$current_language = qtranxf_getLanguage();
	}

	if ($current_language) {
		if (strpos($url, '/'.$current_language.'/wp-json/')) {
			$url = str_replace('/'.$current_language.'/wp-json/', '/wp-json/', $url);
		}
	}

	return $url;
}

add_filter('rest_url', 'rsssl_fix_rest_url_for_wpml', 10, 4);

/**
 * WordPress doesn't allow for translation of chunks resulting of code splitting.
 * Several workarounds have popped up in JetPack and Woocommerce: https://developer.wordpress.com/2022/01/06/wordpress-plugin-i18n-webpack-and-composer/
 * Below is mainly based on the Woocommerce solution, which seems to be the most simple approach. Simplicity is king here.
 *
 * @return array
 */
function rsssl_get_chunk_translations($path = 'settings/build'  ) {
	//get all files from the settings/build folder
	$files = scandir(rsssl_path . $path );
	$json_translations = [];

	// filter the filenames to get the JavaScript and asset filenames
	$jsFilename = '';
	$assetFilename = '';

	foreach ($files as $file) {
		if (strpos($file, 'index.') === 0) {
			if (substr($file, -3) === '.js') {
				$jsFilename = $file;
			} elseif (substr($file, -10) === '.asset.php') {
				$assetFilename = $file;
			}
		}

		if (strpos($file, '.js') === false) {
			continue;
		}
		$chunk_handle = str_replace('.js', '', $file );
		//temporarily register the script, so we can get a translations object.
		wp_register_script( $chunk_handle, plugins_url('build/'.$file, __FILE__), [], true );
		$language_path = defined('rsssl_pro') ? rsssl_path . 'languages' : false;
		$localeData = load_script_textdomain( $chunk_handle, 'really-simple-ssl', $language_path );

		if (!empty($localeData)){
			$json_translations[] = $localeData;
		}
		wp_deregister_script( $chunk_handle );
	}
	if (empty($jsFilename) || empty($assetFilename) ) {
		return [];
	}
	$assetFile     = require( rsssl_path . trailingslashit( $path ) . $assetFilename );
	return [
		'json_translations' => $json_translations,
		'dependencies'  => $assetFile['dependencies'],
		'version'  => $assetFile['version'],
		'js_file'  => $jsFilename,
	];
}

function rsssl_plugin_admin_scripts()
{

	$js_data = rsssl_get_chunk_translations();
	// check if the necessary files are found
	if ( !empty($js_data) ) {
		$handle = 'rsssl-settings';
		wp_enqueue_script( $handle);
		wp_enqueue_script(
			'rsssl-settings',
			plugins_url( 'build/' . $js_data['js_file'], __FILE__ ),
			$js_data['dependencies'],
			$js_data['version'],
			true
		);
		wp_set_script_translations($handle, 'really-simple-ssl');

		wp_localize_script(
			'rsssl-settings',
			'rsssl_settings',
			apply_filters('rsssl_localize_script', [
				'json_translations' => $js_data['json_translations'],
				'menu' => rsssl_menu(),
				'is_bf' => RSSSL()->admin->is_bf(),
				'site_url' => get_rest_url(),
				'plugins_url' => admin_url('update-core.php'),
				'admin_ajax_url' => add_query_arg(
					array(
						'type' => 'errors',
						'action' => 'rsssl_rest_api_fallback'
					),
					admin_url('admin-ajax.php') ),
				'dashboard_url' => rsssl_admin_url(),
				'letsencrypt_url' => rsssl_letsencrypt_wizard_url(),
				'le_generated_by_rsssl' => rsssl_generated_by_rsssl(),
				'upgrade_link' => rsssl_link('pro', 'upgrade' ),
				'ref' => rsssl_get_url_ref(),
				'plugin_url' => rsssl_url,
				'network_link' => network_site_url('plugins.php'),
				'pro_plugin_active' => defined('rsssl_pro'),
				'networkwide_active' => !is_multisite() || rsssl_is_networkwide_active(),//true for single sites and network wide activated
				'nonce' => wp_create_nonce('wp_rest'),//to authenticate the logged-in user
				'rsssl_nonce' => wp_create_nonce('rsssl_nonce'),
				'wpconfig_fix_required' => RSSSL()->admin->do_wpconfig_loadbalancer_fix() && ! RSSSL()->admin->wpconfig_has_fixes() && ! RSSSL()->admin->uses_bitnami(),
				'cloudflare' => rsssl_uses_cloudflare(),
				'email_verified' => rsssl_is_email_verified(),
			])
		);
	}
}

/**
 * Check if this server is behind CloudFlare
 *
 * @return bool
 */
function rsssl_uses_cloudflare(): bool {
	return isset( $_SERVER['HTTP_CF_CONNECTING_IP'] );
}

/**
 * Add SSL menu
 *
 * @return void
 */
function rsssl_add_top_level_menu() {
	if ( ! rsssl_user_can_manage() ) {
		return;
	}

	if ( is_multisite() && rsssl_is_networkwide_active() ) {
		return;
	}

	$count        = RSSSL()->admin->count_plusones();
	$update_count = $count > 0 ? "<span class='update-plugins rsssl-update-count'><span class='update-count'>$count</span></span>" : "";

	$icon_svg = '<?xml version="1.0" encoding="UTF-8"?>
<svg id="rss-menu-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 -15 90 130" width="34" height="34">
    <defs>
        <style>.cls-1{fill:#fff;stroke-width:0px;}</style>
    </defs>
    <g fill="none" stroke-width="2">
        <path class="cls-1" d="M72.92,26.6h-13v-9.4c0-7.6-6.1-13.7-13.7-13.7s-13.8,6.1-13.8,13.7v9.4h-13.1v-9.4C19.32,2.4,31.32,-9.6,46.12,-9.6s26.8,12,26.8,26.8v9.4h0Z"/>
        <rect class="cls-1" x="10.02" y="84.6" width="72.3" height="5.6"/>
        <path class="cls-1" d="M82.32,82H10.02V31.8c0-2.9,2.3-5.2,5.2-5.2h61.9c2.9,0,5.2,2.3,5.2,5.2V82h0ZM64.62,37.8c-2.2-2.2-5.9-2.2-8.2,0l-15.7,15.3l-4.9-4.9c-2.2-2.2-5.9-2.2-8.2,0l-1.9,1.9c-2.2,2.2-2.2,5.9,0,8.2l8.5,8.5c0.1,0.2,0.3,0.4,0.5,0.6l1.9,1.9l4.2,4l3.5-3.5c0.2-0.1,0.4-0.3,0.6-0.5l1.9-1.9c0.2-0.2,0.4-0.4,0.5-0.6l19.1-18.9c2.2-2.2,2.2-5.9,0-8.2l-1.8-1.9Z"/>
    </g>
</svg>';

	$icon_base64 = 'data:image/svg+xml;base64,' . base64_encode($icon_svg);

	$page_hook_suffix = add_menu_page(
		__( "Security", "really-simple-ssl" ),
		__( "Security", "really-simple-ssl" ) . $update_count,
		'manage_security',
		'really-simple-security',
		'rsssl_settings_page',
		$icon_base64,
		100 // This will place it near the bottom of the menu
	);

	add_action( "admin_print_scripts-{$page_hook_suffix}", 'rsssl_plugin_admin_scripts' );
    // Update the page title to prevent issues with an empty title causing strip_tags deprecation warnings
	add_action("load-{$page_hook_suffix}", 'rsssl_set_admin_page_title');
	add_action('admin_head', 'rsssl_override_wordpress_svg_size');

}

add_action( 'admin_menu', 'rsssl_add_top_level_menu' );

function rsssl_override_wordpress_svg_size() {
	echo '<style>
        #adminmenu .toplevel_page_really-simple-security div.wp-menu-image.svg {
            background-size: 23px auto !important;
        }
    </style>';
}

/**
 * @return void
 *
 * Set title of RSSSL admin page
 */
function rsssl_set_admin_page_title() {
	global $title;
	$title = __( "Security", "really-simple-ssl" );
}

/**
 * Render the settings page
 */

function rsssl_settings_page()
{
	if ( ! rsssl_user_can_manage()) {
		return;
	}

	?>
    <div id="really-simple-ssl" class="rsssl"></div>
    <div id="really-simple-ssl-modal"></div>
	<?php
}

/**
 * If the rest api is blocked, the code will try an admin ajax call as fall back.
 *
 * @return void
 */
function rsssl_rest_api_fallback()
{
	$response = $data = [];
	$error    = $action = $test = $do_action = false;

	if ( ! rsssl_user_can_manage()) {
		$error = true;
	}
	//if the site is using this fallback, we want to show a notice
	update_option('rsssl_ajax_fallback_active', time(), false);
	if (isset($_GET['rest_action'])) {
		$action = sanitize_text_field($_GET['rest_action']);
		if (strpos($action, 'reallysimplessl/v1/tests/') !== false) {
			$test = strtolower(str_replace('reallysimplessl/v1/tests/', '', $action));
		}
	}
	$requestData = json_decode(file_get_contents('php://input'), true);
	if ($requestData) {
		$action = $requestData['path'] ?? false;
		$action = sanitize_text_field($action);
		$data = $requestData['data'] ?? false;
		if (strpos($action, 'reallysimplessl/v1/do_action/') !== false) {
			$do_action = strtolower(str_replace('reallysimplessl/v1/do_action/', '', $action));
		}
	}
	if (!$error) {
		if (strpos($action, 'fields/get') !== false) {
			$response = rsssl_rest_api_fields_get();
		} else if (strpos($action, 'fields/set') !== false) {
			$request = new WP_REST_Request();
			$response = rsssl_rest_api_fields_set($request, $data);
		} else if ($test) {
			$request = new WP_REST_Request();
			$data = $_GET['data'] ?? false;
			$data = json_decode(stripcslashes($data));
			$data = (array)$data;
			$nonce = isset($_GET['nonce']) ? sanitize_text_field($_GET['nonce']) : false;
			$id = isset($_GET['id']) ? sanitize_text_field($_GET['id']) : false;
			$state = isset($_GET['state']) ? sanitize_title($_GET['state']) : false;
			$request->set_param('test', $test);
			$request->set_param('state', $state);
			$request->set_param('id', $id);
			$request->set_param('nonce', $nonce);
			//remove
			foreach ($_GET as $key => $value) {
				$data[$key] = sanitize_text_field($value);
			}
			$response = rsssl_run_test($request, $data);
		} elseif ($do_action) {
			$request = new WP_REST_Request();
			$request->set_param('action', $do_action);
			$response = rsssl_do_action($request, $data);
		}
	}
	header("Content-Type: application/json");
	echo json_encode($response);
	exit;
}

add_action('wp_ajax_rsssl_rest_api_fallback', 'rsssl_rest_api_fallback');

add_action('rest_api_init', 'rsssl_settings_rest_route', 10);
function rsssl_settings_rest_route()
{
	if (!rsssl_user_can_manage()) {
		return;
	}

	register_rest_route('reallysimplessl/v1', 'fields/get', array(
		'methods' => 'GET',
		'callback' => 'rsssl_rest_api_fields_get',
		'permission_callback' => function () {
			return rsssl_user_can_manage();
		}
	));

	register_rest_route('reallysimplessl/v1', 'fields/set', array(
		'methods' => 'POST',
		'callback' => 'rsssl_rest_api_fields_set',
		'permission_callback' => function () {
			return rsssl_user_can_manage();
		}
	));

	register_rest_route('reallysimplessl/v1', 'tests/(?P<test>[a-z\_\-]+)', array(
		'methods' => 'GET',
		'callback' => 'rsssl_run_test',
		'permission_callback' => function () {
			return rsssl_user_can_manage();
		}
	));

	register_rest_route('reallysimplessl/v1', 'do_action/(?P<action>[a-z\_\-]+)', array(
		'methods' => 'POST',
		'callback' => 'rsssl_do_action',
		'permission_callback' => function () {
			return rsssl_user_can_manage();
		}
	));

}

/**
 * Store SSL Labs result
 * @param array $data
 *
 * @return array
 */
function rsssl_store_ssl_labs($data)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}
	update_option('rsssl_ssl_labs_data', $data, false);
	return [];
}

function rsssl_remove_fallback_notice()
{
	if (get_option('rsssl_ajax_fallback_active') !== false) {
		delete_option('rsssl_ajax_fallback_active');
	}
}

/**
 * @param WP_REST_Request $request
 * @param array|bool $ajax_data
 *
 * @return void
 */
function rsssl_do_action($request, $ajax_data = false)
{
	if (!rsssl_user_can_manage()) {
		return;
	}

	if (!$ajax_data) {
		rsssl_remove_fallback_notice();
	}
	$action = sanitize_title($request->get_param('action'));
	$data = $ajax_data !== false ? $ajax_data : $request->get_params();

	$nonce = $data['nonce'];
	if (!wp_verify_nonce($nonce, 'rsssl_nonce')) {
		return;
	}
	switch ($action) {
		case 'ssltest_get':
			$response = ['data' => get_option('rsssl_ssl_labs_data')];
			break;
		case 'ssltest_run':
			$response = rsssl_ssltest_run($data);
			break;
		case 'store_ssl_labs':
			$response = rsssl_store_ssl_labs($data);
			break;
		case 'send_test_mail':
			$mailer = new rsssl_mailer();
			$response = $mailer->send_test_mail();
			break;
		case 'send_verification_mail':
			$mailer = new rsssl_mailer();
			$response = $mailer->send_verification_mail( rsssl_get_option('notifications_email_address') );
			break;
		case 'plugin_actions':
			$response = rsssl_plugin_actions($data);
			break;
		case 'clear_cache':
			$response = rsssl_clear_test_caches($data);
			break;
		case 'fix':
			$response = rsssl_fix($data);
			break;
		case 'otherpluginsdata':
			$response = rsssl_other_plugins_data();
			break;
		case 'get_roles':
			$roles = rsssl_get_roles();
			$response = [];
			$response['roles'] = $roles;
			break;
		case 'get_hosts':
			$response = [];
			if ( !class_exists('rsssl_le_hosts')) {
				require_once( rsssl_path . 'lets-encrypt/config/class-hosts.php');
				$response['hosts'] = ( new rsssl_le_hosts() )->hosts;
			} else {
				$response['hosts'] = RSSSL_LE()->hosts->hosts;
            }
			break;
		default:
			$response = apply_filters("rsssl_do_action", [], $action, $data);
	}

	if (is_array($response)) {
		$response['request_success'] = true;
	}

	return $response;
}

/**
 * @param array $data
 *
 * @return array
 */
function rsssl_clear_test_caches($data)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}

	$cache_id = sanitize_title($data['cache_id']);

	do_action('rsssl_clear_test_caches', $data);
	return [];
}

/**
 * @param array $data
 *
 * @return array
 */
function rsssl_fix($data)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}

	$fix_id = sanitize_title($data['fix_id']);
    $output = [];
	$output = apply_filters('rsssl_run_fix', $output, $fix_id);
	return $output;
}

/**
 * Process plugin installation or activation actions
 *
 * @param array $data
 *
 * @return array
 */

function rsssl_plugin_actions($data)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}
	$slug = sanitize_title($data['slug']);
	$action = sanitize_title($data['pluginAction']);
	$installer = new rsssl_installer($slug);
	if ($action === 'download') {
		$installer->download_plugin();
	} elseif ($action === 'activate') {
		$installer->activate_plugin();
	}

	return rsssl_other_plugins_data($slug);
}

/**
 * Run a request to SSL Labs
 *
 * @param $data
 *
 * @return string
 */
function rsssl_ssltest_run( $data ) {
	if ( ! rsssl_user_can_manage() ) {
		return '';
	}
	$url      = $data['url'];
	$response = wp_safe_remote_get( $url );
	$data     = wp_remote_retrieve_body( $response );
	if ( empty( $data ) ) {
		$data = [ 'errors' => 'Request failed, please try again.' ];
	}

	return $data;
}

/**
 * @param WP_REST_Request $request
 *
 * @return array
 */
function rsssl_run_test($request, $ajax_data = false)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}
	if (!$ajax_data) {
		rsssl_remove_fallback_notice();
	}
	$nonce = $request->get_param('nonce');
	if (!wp_verify_nonce($nonce, 'rsssl_nonce')) {
		return [];
	}
	$data = $ajax_data !== false ? $ajax_data : $request->get_params();
	$test = sanitize_title($request->get_param('test'));
	$state = $request->get_param('state');
	$state = $state !== 'undefined' && $state !== 'false' ? $state : false;
	switch ($test) {
		case 'progressdata':
			$response = RSSSL()->progress->get();
			break;
		case 'dismiss_task':
			$response = RSSSL()->progress->dismiss_task($state);
			break;
		default:
			$response = apply_filters("rsssl_run_test", [], $test, $data);
	}
	if (is_array($response)) {
		$response['request_success'] = true;
	}
	return $response;
}

/**
 * Get plugin data for other plugin section
 * @param string $slug
 * @return array
 */
function rsssl_other_plugins_data($slug = false)
{
	if (!rsssl_user_can_manage()) {
		return [];
	}
	$plugins = array(
		[
			'slug' => 'complianz-gdpr',
			'constant_free' => 'cmplz_plugin',
			'constant_premium' => 'cmplz_premium',
			'wordpress_url' => 'https://wordpress.org/plugins/complianz-gdpr/',
			'upgrade_url' => 'https://complianz.io/pricing?src=rsssl-plugin',
			'title' => __("Complianz - Consent Management as it should be", "really-simple-ssl"),
		],
		[
			'slug' => 'complianz-terms-conditions',
			'constant_free' => 'cmplz_tc_version',
			'wordpress_url' => 'https://wordpress.org/plugins/complianz-terms-conditions/',
			'upgrade_url' => 'https://complianz.io?src=rsssl-plugin',
			'title' => 'Complianz - ' . __("Terms and Conditions", "really-simple-ssl"),
		],
	);

	foreach ($plugins as $index => $plugin) {
		$installer = new rsssl_installer($plugin['slug']);
		if (isset($plugin['constant_premium']) && defined($plugin['constant_premium'])) {
			$plugins[$index]['pluginAction'] = 'installed';
		} else if (!$installer->plugin_is_downloaded() && !$installer->plugin_is_activated()) {
			$plugins[$index]['pluginAction'] = 'download';
		} else if ($installer->plugin_is_downloaded() && !$installer->plugin_is_activated()) {
			$plugins[$index]['pluginAction'] = 'activate';
		} else {
			if (isset($plugin['constant_premium'])) {
				$plugins[$index]['pluginAction'] = 'upgrade-to-premium';
			} else {
				$plugins[$index]['pluginAction'] = 'installed';
			}
		}
	}

	if ($slug) {
		foreach ($plugins as $key => $plugin) {
			if ($plugin['slug'] === $slug) {
				return $plugin;
			}
		}
	}
	return ['plugins' => $plugins];

}

/**
 * List of allowed field types
 * @param $type
 *
 * @return string|bool
 */
function rsssl_sanitize_field_type($type) {
    $types = [
        'hidden',
        'license',
        'database',
        'checkbox',
        'password',
        'radio',
        'text',
        'textarea',
        'number',
        'email',
        'select',
        'host',
        'permissionspolicy',
        'learningmode',
        'mixedcontentscan',
        'vulnerablemeasures',
        'LetsEncrypt',
        'postdropdown',
        'two_fa_roles',
        'roles_enabled_dropdown',
        'roles_dropdown',
        'captcha',
        'captcha_key',
    ];
    if (in_array($type, $types, true)) {
        return $type;
    }
    // re-moving checkbox as a return type to the end of the function
    return false;
}

/**
 * @param WP_REST_Request $request
 * @param array $ajax_data
 *
 * @return array
 */
function rsssl_rest_api_fields_set(WP_REST_Request $request, $ajax_data = false): array
{
	if (!rsssl_user_can_manage()) {
		return [];
	}

	$fields = $ajax_data ?: $request->get_json_params();
	//get the nonce
	$nonce = false;
	foreach ($fields as $index => $field) {
		if (isset($field['nonce'])) {
			$nonce = $field['nonce'];
			unset($fields[$index]);
		}
	}

	if (!wp_verify_nonce($nonce, 'rsssl_nonce')) {
		return [];
	}

	$config_fields = rsssl_fields(false);
	$config_ids = array_column($config_fields, 'id');
	foreach ($fields as $index => $field) {
		$config_field_index = array_search($field['id'], $config_ids);
		$config_field = $config_fields[$config_field_index];
		if ($config_field_index === false) {
			unset($fields[$index]);
			continue;
		}
		$type = rsssl_sanitize_field_type($field['type']);
        if ($type === false) {
            return [
                'success' => false,
                'error'   => 'Invalid field type provided for field ' . sanitize_text_field($field['id']),
            ];
        }
		$field_id = sanitize_text_field($field['id']);
		$value = rsssl_sanitize_field($field['value'], $type, $field_id);
		//if an endpoint is defined, we use that endpoint instead
		if (isset($config_field['data_endpoint'])) {
			//the updateItemId allows us to update one specific item in a field set.
			$update_item_id = isset($field['updateItemId']) ? $field['updateItemId'] : false;
			$action = isset($field['action']) && $field['action'] === 'delete' ? 'delete' : 'update';
			$endpoint = $config_field['data_endpoint'];
			if (is_array($endpoint)) {
				$main = $endpoint[0];
				$class = $endpoint[1];
				$function = $endpoint[2];
				if (function_exists($main)) {
					$main()->$class->$function($value, $update_item_id, $action);
				}
			} else if (function_exists($endpoint)) {
				$endpoint($value, $update_item_id, $action);
			}

			unset($fields[$index]);
			continue;
		}

		$field['value'] = $value;
		$fields[$index] = $field;
	}

	if (is_multisite() && rsssl_is_networkwide_active()) {
		$options = get_site_option('rsssl_options', []);
	} else {
		$options = get_option('rsssl_options', []);
	}

	//build a new options array
	foreach ($fields as $field) {
		$prev_value = isset($options[$field['id']]) ? $options[$field['id']] : false;
		do_action("rsssl_before_save_option", $field['id'], $field['value'], $prev_value, $field['type']);
		$options[$field['id']] = apply_filters("rsssl_fieldvalue", $field['value'], $field['id'], $field['type']);
	}
	if (!empty($options)) {
		if (is_multisite() && rsssl_is_networkwide_active()) {
			update_site_option('rsssl_options', $options);
		} else {
			update_option('rsssl_options', $options);
		}
	}
	RSSSL()->admin->clear_admin_notices_cache();
	do_action('rsssl_after_saved_fields', $fields );
	foreach ( $fields as $field ) {
		do_action( "rsssl_after_save_field", $field['id'], $field['value'], $prev_value, $field['type'] );
	}
	return [
		'success' => true,
		'progress' => RSSSL()->progress->get(),
		'fields' => rsssl_fields(true),
	];
}

/**
 * Update a rsssl option
 * @param string $name
 * @param mixed $value
 *
 * @return void
 */

function rsssl_update_option($name, $value)
{
	if (!rsssl_user_can_manage()) {
		return;
	}
	$config_fields = rsssl_fields(false);
	$config_ids = array_column($config_fields, 'id');
	$config_field_index = array_search($name, $config_ids);
	if ($config_field_index === false) {
		return;
	}

	$config_field = $config_fields[$config_field_index];
	$type = $config_field['type'] ?? false;
	if (!$type) {
		return;
	}
	if (is_multisite() && rsssl_is_networkwide_active()) {
		$options = get_site_option('rsssl_options', []);
	} else {
		$options = get_option('rsssl_options', []);
	}
	if (!is_array($options)) $options = [];
	$prev_value = $options[$name] ?? false;
	$name = sanitize_text_field($name);
	$type = rsssl_sanitize_field_type($config_field['type']);
	$value = rsssl_sanitize_field($value, $type, $name);
	$value = apply_filters("rsssl_fieldvalue", $value, sanitize_text_field($name), $type);
	#skip if value wasn't changed
	if (isset($options[$name]) && $options[$name] === $value) {
		return;
	}

	$options[$name] = $value;
	if ( is_multisite() && rsssl_is_networkwide_active() ) {
		update_site_option( 'rsssl_options', $options );
	} else {
		update_option( 'rsssl_options', $options );
	}
	$config_field['value'] = $value;
	RSSSL()->admin->clear_admin_notices_cache();
	do_action('rsssl_after_saved_fields',[$config_field] );
	do_action( "rsssl_after_save_field", $name, $value, $prev_value, $type );
}

/**
 * Get the rest api fields
 * @return array
 */
function rsssl_rest_api_fields_get()
{
	if (!rsssl_user_can_manage()) {
		return [];
	}

	$output = array();
	$fields = rsssl_fields();
	foreach ($fields as $index => $field) {
		/**
		 * Load data from source
		 */
		if (isset($field['data_source'])) {
			$data_source = $field['data_source'];
			if (is_array($data_source)) {
				$main = $data_source[0];
				$class = $data_source[1];
				$function = $data_source[2];
				$field['value'] = [];
				if (function_exists($main)) {
					$field['value'] = $main()->$class->$function();
				}
			} else if (function_exists($field['data_source'])) {
				$func = $field['data_source'];
				$field['value'] = $func();
			}
		}

		$fields[$index] = $field;
	}

	$output['fields'] = $fields;
	$output['request_success'] = true;
	$output['progress'] = RSSSL()->progress->get();
	return apply_filters('rsssl_rest_api_fields_get', $output);
}

/**
 * Sanitize a field
 *
 * @param mixed $value
 * @param string $type
 * @oaram string $id
 *
 * @return array|bool|int|string|void
 */
function rsssl_sanitize_field($value, string $type, string $id)
{
	switch ($type) {
		case 'checkbox':
		case 'number':
			return (int)$value;
		case 'hidden':
			return sanitize_title($value);
		case 'select':
		case 'host':
		case 'text':
		case 'license':
		case 'password':
		case 'captcha_key':
		case 'postdropdown':
			return sanitize_text_field($value);
		case 'textarea':
    		return wp_kses($value, array());
		case 'multicheckbox':
			if (!is_array($value)) {
				$value = array($value);
			}
			return array_map('sanitize_text_field', $value);
		case 'email':
			return sanitize_email($value);
		case 'url':
			return esc_url_raw($value);
		case 'permissionspolicy':
			return rsssl_sanitize_permissions_policy($value, $type, $id);
		case 'learningmode':
			return rsssl_sanitize_datatable($value, $type, $id);
		case 'mixedcontentscan':
			return $value;
		case 'roles_dropdown':
		case 'roles_enabled_dropdown':
		case 'two_fa_roles':
			$value = !is_array($value) ? [] : $value;
			$roles = rsssl_get_roles();
			foreach ($value as $index => $role) {
				if (! in_array( $role, $roles, true ) ) {
					unset($value[$index]);
				}
			}
			return $value;
		default:
			return sanitize_text_field($value);
	}
}

/**
 * Dedicated permission policy sanitization
 *
 * @param $value
 * @param $type
 * @param $field_name
 *
 * @return array|false
 */
function rsssl_sanitize_permissions_policy($value, $type, $field_name)
{
	$possible_keys = apply_filters("rsssl_datatable_datatypes_$type", [
		'id' => 'string',
		'title' => 'string',
		'status' => 'boolean',
	]);
	// Datatable array will look something like this, whith 0 the row index, and id, title the col indexes.
	// [0] => Array
	//	(
	//		[id] => camera
	//		[title] => Camera
	//	    [value] => ()
	//      [status] => 1/0
	//   )
	//)
	$config_fields = rsssl_fields(false);
	//check if there is a default available
	$default = false;
	foreach ($config_fields as $config_field) {
		if ($config_field['id'] === $field_name) {
			$default = isset($config_field['default']) ? $config_field['default'] : false;
		}
	}

	$stored_ids = [];
	if (!is_array($value)) {
		return $default;
	} else {
		foreach ($value as $row_index => $row) {
			//check if we have invalid values
			if (is_array($row)) {
				foreach ($row as $column_index => $row_value) {
					if ($column_index === 'id' && $row_value === false) {
						unset($value[$column_index]);
					}
				}
			}

			//has to be an array.
			if (!is_array($row)) {
				if (isset($default[$row_index])) {
					$value[$row_index] = $default[$row_index];
				} else {
					unset($value[$row_index]);
				}
			}

			foreach ($row as $col_index => $col_value) {
				if (!isset($possible_keys[$col_index])) {
					unset($value[$row_index][$col_index]);
				} else {
					$datatype = $possible_keys[$col_index];
					switch ($datatype) {
						case 'string':
							$value[$row_index][$col_index] = sanitize_text_field($col_value);
							break;
						case 'int':
						case 'boolean':
						default:
							$value[$row_index][$col_index] = intval($col_value);
							break;
					}
				}
			}

			//Ensure that all required keys are set with at least an empty value
			foreach ($possible_keys as $key => $data_type) {
				if (!isset($value[$row_index][$key])) {
					$value[$row_index][$key] = false;
				}
			}
		}
	}

	//ensure that there are no duplicate ids
	foreach ($value as $index => $item) {
		if (in_array($item['id'], $stored_ids)) {
			unset($value[$index]);
			continue;
		}
		$stored_ids[] = $item['id'];
	}

	//if the default contains items not in the setting (newly added), add them.
	if (count($value) < count($default)) {
		foreach ($default as $def_row_index => $def_row) {
			//check if it is available in the array. If not, add
			if (!in_array($def_row['id'], $stored_ids)) {
				$value[] = $def_row;
			}
		}
	}
	return $value;
}

function rsssl_sanitize_datatable($value, $type, $field_name)
{
	$possible_keys = apply_filters("rsssl_datatable_datatypes_$type", [
		'id' => 'string',
		'title' => 'string',
		'status' => 'boolean',
	]);

	if (!is_array($value)) {
		return false;
	} else {
		foreach ($value as $row_index => $row) {
			//check if we have invalid values
			if (is_array($row)) {
				foreach ($row as $column_index => $row_value) {
					if ($column_index === 'id' && $row_value === false) {
						unset($value[$column_index]);
					}
				}
			}

			//has to be an array.
			if (!is_array($row)) {
				unset($value[$row_index]);
			}

			foreach ($row as $col_index => $col_value) {
				if (!isset($possible_keys[$col_index])) {
					unset($value[$row_index][$col_index]);
				} else {
					$datatype = $possible_keys[$col_index];
					switch ($datatype) {
						case 'string':
							$value[$row_index][$col_index] = sanitize_text_field($col_value);
							break;
						case 'int':
						case 'boolean':
						default:
							$value[$row_index][$col_index] = intval($col_value);
							break;
					}
				}
			}

			//Ensure that all required keys are set with at least an empty value
			foreach ($possible_keys as $key => $data_type) {
				if (!isset($value[$row_index][$key])) {
					$value[$row_index][$key] = false;
				}
			}
		}
	}
	return $value;
}


/**
 * Check if the server side conditions apply
 *
 * @param array $conditions
 *
 * @return bool
 */

function rsssl_conditions_apply(array $conditions)
{

	$defaults = ['relation' => 'AND'];
	$conditions = wp_parse_args($conditions, $defaults);
	$relation = $conditions['relation'] === 'AND' ? 'AND' : 'OR';
	unset($conditions['relation']);
	$condition_applies = true;
	foreach ($conditions as $condition => $condition_value) {
		$invert = substr($condition, 1) === '!';
		$condition = ltrim($condition, '!');

		if (is_array($condition_value)) {
			$this_condition_applies = rsssl_conditions_apply($condition_value);
		} else {
			//check if it's a function
			if (substr($condition, -2) === '()') {
				$func = $condition;
				if (preg_match('/(.*)\(\)\-\>(.*)->(.*)/i', $func, $matches)) {
					$base = $matches[1];
					$class = $matches[2];
					$func = $matches[3];
					$func = str_replace('()', '', $func);
					$this_condition_applies = call_user_func(array($base()->{$class}, $func)) === $condition_value;
				} else {
					$func = str_replace('()', '', $func);
					$this_condition_applies = $func() === $condition_value;
				}
			} else {
				$var = $condition;
				if (preg_match('/(.*)\(\)\-\>(.*)->(.*)/i', $var, $matches)) {
					$base = $matches[1];
					$class = $matches[2];
					$var = $matches[3];
					$this_condition_applies = $base()->{$class}->_get($var) === $condition_value;
				} else {
					$this_condition_applies = rsssl_get_option($var) === $condition_value;
				}
			}

			if ($invert) {
				$this_condition_applies = !$this_condition_applies;
			}

		}

		if ($relation === 'AND') {
			$condition_applies = $condition_applies && $this_condition_applies;
		} else {
			$condition_applies = $condition_applies || $this_condition_applies;
		}
	}

	return $condition_applies;
}

/**
 * Fetch all user roles.
 *
 * Tries to get roles from cache first. If roles are not in cache, it fetches them and stores them in cache.
 *
 * @return array An array of roles, each role being an associative array with 'label' and 'value' keys.
 */
function rsssl_get_roles( ): array {
	if ( ! rsssl_admin_logged_in() ) {
		return [];
	}

	global $wp_roles;

	// Try to get roles from cache
	$roles = wp_cache_get( 'rsssl_roles' );

	// If roles are not in cache, fetch and set cache
	if ( ! $roles ) {
		// Just return the names, not the capabilities
		$roles_names = array_keys( $wp_roles->roles );

		// Extract unique role values from the role names
		$roles = array_values( array_unique( $roles_names ));
		// Set the roles in cache for future use
		wp_cache_set( 'rsssl_roles', $roles );
	}

	return $roles;
}

/**
 * @param $response
 * @param $user
 * @param $request
 *
 * @return mixed
 *
 * Add user roles to /users endpoint
 */
function rsssl_add_user_role_to_api_response( $response, $user, $request ) {
	if ( rsssl_is_logged_in_rest() ) {
		$data          = $response->get_data();
		$data['roles'] = $user->roles;
		$response->set_data( $data );
	}

	return $response;
}
add_filter( 'rest_prepare_user', 'rsssl_add_user_role_to_api_response', 10, 3 );

if ( ! function_exists('rsssl_change_email_status_on_email_change' ) ) {
	function rsssl_change_email_status_on_email_change(string $field_id, $new_value, $previous_value) {
		if ( $field_id === 'notifications_email_address' && $new_value !== $previous_value ) {
			update_option( 'rsssl_email_verification_status', 'email_changed' );
		}
	}
}

add_filter('rsssl_after_save_field', 'rsssl_change_email_status_on_email_change', 10, 3);
الذكاء الاصطناعي في مصر تطور بلا تشريع فمن يتحمل المسؤولية؟ – tahkoom.com
تفاعل

الذكاء الاصطناعي في مصر تطور بلا تشريع فمن يتحمل المسؤولية؟

كتبت شروق عارف                                                                                                                                                    يشهد العالم تطورا غير مسبوق في التكنولوجيا، حيث أصبح الذكاء الاصطناعي قوة مؤثرة تعيد تشكيل حياتنا وتغيّر قواعد العديد من المجالات. ورغم ما يتيحه هذا التقدم من فرص واسعة، إلا أنه يثير تحديات ومخاوف، خاصة في ظل غياب تشريعات واضحة تنظم استخدامه في مجالات حساسة كالجراحة، والسيارات ذاتية القيادة، والمجال القانوني. هذا الواقع يطرح تساؤلات مهمة، أبرزها: من يتحمل المسؤولية عند حدوث خطأ؟ وتواجه مصر اليوم تحديا في سن قوانين تحمي حقوق الناس وتواكب في الوقت نفسه التقدم التكنولوجي                                                                                                                       

لا قانون للذكاء الاصطناعي حتى الان                                                                                               

صرح المحامي محمد عاطف  بأن الذكاء الاصطناعي لا يخضع حتى الآن لإطار قانوني واضح ومحدد.
و لم يتم إصدار قانون شامل ينظم استخداماته حتى الآن.

وأوضح أنه لا يجوز قانونًا للذكاء الاصطناعي تقديم استشارات قانونية، حيث إن هذه المهام يجب أن تكون من اختصاص محامي مرخص أو جهة قانونية معترف بها، لضمان صحة المعلومات .

وفي ما يتعلق بالمسؤولية الطبية، أشار إلى أن الطبيب هو المسؤول الأول عن الخطأ الطبي، باعتباره صاحب القرار والمتخصص في تقديم الرعاية الصحية، وبالتالي فهو الذي يُسأل قانونًا عند وقوع أي تقصير أو إهمال.

أما في حالات حوادث السير، فقد بين أن السائق هو المسؤول قانونيًا عن أي خطأ يقع أثناء القيادة، لأنه هو المتحكم .
وأضاف أن القانون لا يزال غير مستوعب بشكل كامل لمفهوم القيادة الذاتية، وبالتالي لا يحمل الذكاء الاصطناعي أي مسؤولية في هذا السياق حتى الآن.

من جانبه، أوضح المحامي الجنائي محمد علي أن الذكاء الاصطناعي لديه القدرة على تقديم استشارات أو خدمات قانونية.
ولكن لا بد أن نفرق بين دوره ودور المحامي، فالمحامي لا يعتمد فقط على المعلومات، بل على فهمه العميق للقانون وظروف كل قضية، وهو ما لا يستطيع الذكاء الاصطناعي تقديمه، لأنه في النهاية مجرد أداة.

كما أن الذكاء الاصطناعي يمكنه المساعدة في الوصول إلى مواد قانونية أو شرح بعض المفاهيم، لكنه لا يقدم حلولًا قانونية كاملة، ولا يستطيع التعامل مع تفاصيل كل حالة على حدة كما يفعل المحامي البشري.

وأشار إلى أن مصر لا تمتلك حتى الآن قانونًا خاصًا ينظم الذكاء الاصطناعي.
كما لا يوجد ما يمنع قانونًا استخدام أدوات الذكاء الاصطناعي في تقديم استشارات قانونية، لكن لا يمكن الاعتماد عليها كبديل عن المحامي المرخص، حيث يشترط قانون المحاماة أن تكون المرافعات والتوقيعات القانونية صادرة عن محامي معتمد من النقابة.

وفي المجال الطبي، أوضح أن القانون المصري لا يميز بوضوح بين الخطأ الناتج عن الإنسان والخطأ الناتج عن الذكاء الاصطناعي.
فإذا وقع ضرر نتيجة استخدام أدوات مثل الروبوتات الجراحية أو أنظمة التشخيص، فإن المسؤولية تقع غالبًا على الطبيب.

أما فيما يخص السيارات ذاتية القيادة، فأكد أن مصر لا تملك إطارًا قانونيًا ينظمها حتى الآن.
وفي حال وقوع حادث، قد تتحمل المسؤولية إما الشركة المصنعة أو مالك السيارة، حسب ظروف الحادث.

من جانبه، أكد المحامي المدني رامي أبو رية بأن مصطلح الذكاء الاصطناعي يعد تعبيرا فضفاضا، مما يجعل من السهل القول بأنه لا يوجد قانون محدد ينظم استخدامه.
إلا أن الواقع أكثر دقة فبمجرد تفكيك المصطلح والنظر في كل مجال تُستخدم فيه التكنولوجيا المعتمدة على الذكاء الاصطناعي، نجد أن القوانين الحالية تنظم هذه الاستخدامات بشكل أو بآخر.

وأكد على أهمية تحديد نوع المسؤولية القانونية عند مناقشة الأطر التنظيمية للذكاء الاصطناعي، موضحًا أن الحديث هنا ينصب على المسؤولية المدنية، التي تنقسم بدورها إلى نوعين: المسؤولية العقدية  والمسؤولية التقصيرية، التي تُعد الأقرب لتطبيقات الذكاء الاصطناعي في الوقت الراهن.

وأوضح أن المسؤولية التقصيرية تقوم على ثلاثة عناصر: الخطأ، والضرر، وعلاقة السببية، وهو ما تنظمه المادة 163 من القانون المدني المصري.
وأعطى مثالًا على ذلك بالسيارات ذاتية القيادة، مشيرًا إلى أنها تخضع لأحكام المادة 178 من القانون المدني، التي تتعلق بمسؤولية حارس الأشياء، أي الشخص الذي يملك السيطرة الفعلية على الشيء الذي قد يُسبب ضررًا للغير.
وبناءً عليه، فإن مالك أو مشغل السيارة ذاتية القيادة هو المسؤول مدنيًا عن أي ضرر ناتج عنها.

وفيما يتعلق باستخدام الذكاء الاصطناعي في تقديم الاستشارات القانونية، أشار أبو رية إلى أن هذه التقنية يمكنها حاليًا توليد نصوص قانونية تُقدَّم على هيئة استشارات، لكنها لا تستطيع تطبيقها فعليًا.
وقد تتضمن هذه الاستشارات معلومات عامة متداولة، أو تفاصيل دقيقة لا يعرفها سوى المتخصصين، ما قد يشكّل خطرًا على مصلحة من يطلب الاستشارة دون الرجوع إلى مختص بشري.

صرّحت الأستاذة هند توفيق، المحامية المتخصصة بالإستئناف العالي بأن استخدام الذكاء الاصطناعي في مصر يخضع لإطار قانوني واضح، حيث ينظمه قانون حماية البيانات الشخصية الصادر عام 2020، بالإضافة إلى قانون مكافحة جرائم تقنية المعلومات لسنة 2018، ما يضع استخدام هذه التكنولوجيا تحت الرقابة القانونية.

وأوضحت أن الذكاء الاصطناعي يمكن الاستفادة منه في تقديم استشارات وآراء قانونية أو خدمات مساعدة، مؤكدة على استخدامه بشكل فعلي في الأبحاث القانونية وصياغة المذكرات، إلا أن هذه الأدوات لا تحمل طابعًا رسميًا، ويمكن الاعتماد عليها كمصدر تمهيدي أو مساعد، لا أكثر.

وفيما يتعلق بالمسؤولية القانونية في حالة الأخطاء الطبية الناتجة عن استخدام الروبوتات، أكدت أن هناك شقين للمساءلة: جنائي ومدني. ففي الشق الجنائي، يُعد الروبوت بمثابة أداة جراحية، وأي خلل ناتج عنه يؤدي إلى مساءلة الطبيب جنائيًا بتهمة القتل أو الإصابة الخطأ، وفقًا للضرر الواقع. أما في الشق المدني، فالمسؤولية تقع على الطبيب كذلك، باعتبارها مسؤولية تقصيرية، مضيفة أن القانون المدني المصري يتضمن مفهوم “مسؤولية حارس الأشياء”، والتي يمكن تطبيقها على الروبوت باعتباره شيئًا ماديًا، مما يرتب تعويضًا مدنيًا عن الضرر.

وبالنسبة للحوادث الناجمة عن السيارات ذاتية القيادة، أوضحت أن المبدأ نفسه ينطبق؛ حيث يُسأل مالك السيارة مدنيًا، ما لم يثبت أن العطل ناتج عن خلل تقني أو عيب مصنعي، مع تأكيده على اتخاذه الاحتياطات اللازمة. أما من الناحية الجنائية، فلا يوجد حتى الآن نص قانوني واضح يعالج هذه الحالة.

وفي تقييمها للتأثير الاقتصادي للذكاء الاصطناعي، شددت الأستاذة هند على أن هذه التكنولوجيا باتت تمثل خطرًا حقيقيًا على العديد من المهن، خصوصًا تلك التي تعتمد على المهارات الذهنية، مثل مهنة المحاماة والقضاء. لكنها أوضحت أن الوضع في مصر يختلف، إذ لا يمكن الاعتماد كليًا على الذكاء الاصطناعي في تحقيق العدالة، بسبب الطبيعة البشرية لتكوين قناعة القاضي واستنباط القرائن، وهو ما لا تستطيع الخوارزميات محاكاته حتى الآن.

واختتمت حديثها قائلة: “من يعلم؟! ربما نشهد بعد سنوات قليلة طفرة جديدة تجعل الذكاء الاصطناعي قادراً على أداء مهام لم نكن نتخيل أن يفعلها. منذ أربعين عامًا، لو قال لنا أحد أننا سنتحدث اليوم عبر جهاز يسمى الموبايل ونتبادل الرسائل الإلكترونية، لكنا اتهمناه بالجنون”.

 

لم يعد الذكاء الاصطناعي مجرد فكرة مستقبلية، بل أصبح واقع نعيشه ، ودخل مجالات حساسة تمس حياة الناس بشكل مباشر.
ومع هذا الانتشار السريع، يظل القانون في مصر متأخرًا عن مواكبة هذا التطور، فلا توجد تشريعات واضحة تحدد من المسؤول عند وقوع الخطأ.
ولهذا، فإن وضع إطار قانوني ينظم استخدام الذكاء الاصطناعي أصبح ضرورة لا تحتمل التأجيل، لحماية الحقوق وضمان الاستخدام الآمن والعادل لهذه التكنولوجيا.

اظهر المزيد

مقالات ذات صلة

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى