File "nospam_confirm_action.php"

Full path: /home/argothem/www/organecyberpresse/plugins/auto/nospam/v3.0.0/action/nospam_confirm_action.php
File size: 7.57 KB
MIME-type: text/x-php
Charset: utf-8

<?php
/**
 * Plugin No-SPAM
 * (c) 2008-2019 Cedric Morin Yterium&Nursit
 * Licence GPL
 *
 */


define('_DIR_CONFIRM_ACTIONS', 'actions_a_confirmer');

/**
 * Traiter la confirmation d'action envoyee par le navigateur apres le POST du formulaire
 */
function action_nospam_confirm_action_dist() {

	$securiser_action = charger_fonction('securiser_action', 'inc');
	$hash = $securiser_action();

	$dir_actions = sous_repertoire(_DIR_TMP,_DIR_CONFIRM_ACTIONS);
	if (file_exists($fichier_action = $dir_actions. $hash . '.json')) {

		lire_fichier($fichier_action, $desc_json);
		if ($desc_json and $hash === nospam_hash_action($desc_json)) {

			if ($desc = json_decode($desc_json, true)) {
				// on move ce fichier, le temps de l'execution, pour eviter une double exec (les navs font parfois un double hit sur l'iframe)
				@rename($fichier_action, $fichier_action = $fichier_action . ".inprogress");

				// si on a fournit un time alors il faut ajouter l'action dans la queue
				if (!is_null($desc['time'])) {
					spip_log("nospam_confirm_action_dist $hash: ajout de l'action a job_queue $desc_json", 'nospam' . _LOG_DEBUG);
					job_queue_add($desc['function'], $desc['description'], $desc['arguments'], $desc['file'], false, $desc['time']);
				}
				else {
					$fonction = $desc['function'];
					if (strlen($inclure = trim($desc['file']))) {
						if (substr($inclure, -1) == '/') { // c'est un chemin pour charger_fonction
							$f = charger_fonction($fonction, rtrim($inclure, '/'), false);
							if ($f) {
								$fonction = $f;
							}
						} else {
							include_spip($inclure);
						}
					}

					if (!function_exists($fonction)) {
						spip_log("nospam_confirm_action_dist $hash: fonction $fonction ($inclure) inexistante $desc_json", 'nospam' . _LOG_ERREUR);
					}
					else {
						$res = call_user_func_array($fonction, $desc['arguments']);
						spip_log("nospam_confirm_action_dist $hash: execution de $fonction() $desc_json RES=" . var_export($res,true), 'nospam' . _LOG_DEBUG);
					}
				}
			}
			else {
				spip_log("nospam_confirm_action_dist:contenu action $desc_json invalide", 'nospam' . _LOG_ERREUR);
			}
		}
		else {
			spip_log("nospam_confirm_action_dist:hash $hash errone: contenu action $desc_json", 'nospam' . _LOG_ERREUR);
		}

		// dans tous les cas on purge ce fichier, l'action est faite ou impossible
		@unlink($fichier_action);
	}
	else {
		// pas la peine de loger si le fichier .inprogress est la, c'est un autre thread qui s'en occupe
		if (!file_exists($fichier_action . '.inprogress')) {
			spip_log("nospam_confirm_action_dist:hash $hash errone: fichier $fichier_action absent (doublon deja execute ?)", 'nospam' . _LOG_ERREUR);
		}
	}

	// supprimer les actions plus vieilles que 5mn en les logeant
	$old_time = $_SERVER['REQUEST_TIME'] - 5 * 60;
	nospam_purge_actions($dir_actions, ['mtime' => $old_time, 'limit' => 1000]);

	// et on renvoie un html minimum
	if (!_request('redirect')) {
		include_spip('inc/headers');
		http_response_code(204); // No Content
		header("Connection: close");
	}
}


/**
 * Generer le HTML a afficher pour faire confirmer une action par l'utilisateur a son insu
 * (antispam qui declenche donc l'action uniquement si l'utilisateur charge les ressources de la page)
 *
 * @param string $function
 * @param string $description
 * @param array $arguments
 * @param string $file
 * @param null $time
 * @param string $method
 * @return string
 */
function nospam_confirm_action_prepare(
	$function,
	$description,
	$arguments = array(),
	$file = '',
	$time = null,
	$method = 'script') {

	// on stocke le descriptif de l'action a lancer dans un fichier
	$desc = [
		'function' => $function,
		'description' => $description,
		'arguments' => $arguments,
		'file' => $file,
		'time' => $time,
		// et des infos pour qualifier les spammeurs plus tard si besoin
		'ip' => $GLOBALS['ip'],
		'date' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']), // pour les logs, on met la date de la demande d'action
		'ua' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'undefined',
	];
	$desc = json_encode($desc);

	$dir_actions = sous_repertoire(_DIR_TMP,_DIR_CONFIRM_ACTIONS);

	$hash = nospam_hash_action($desc);
	ecrire_fichier($dir_actions . $hash . ".json", $desc);

	include_spip('inc/actions');
	include_spip('inc/filtres');
	$url_action = str_replace("&amp;", "&", generer_action_auteur("nospam_confirm_action", $hash));
	$url_action_redirect = parametre_url($url_action, 'redirect', self(), '&');

	switch ($method) {
		case 'iframe':
			$title = attribut_html(_T('nospam:info_alt_antispam'));
			$html_action = "<iframe src='$url_action' width='1' height='1' style='display:inline-block;border:0;background:transparent;overflow:hidden;' title='$title'></iframe>";
			break;

		case 'script':
		default:

			$bouton_action = charger_filtre('bouton_action');
			$libelle = attribut_html(_T('nospam:libelle_je_ne_suis_pas_un_robot'));
			$html_action = $bouton_action($libelle, $url_action_redirect, 'btn-primary btn-sm btn-antispam');

			$js = "jQuery.ajax({url: '{$url_action}'}).done(function(){jQuery('.nospam-checkbox').addClass('checked');})";
			$html_action = "<span class='nospam-checkbox small'></span><script>$js</script><noscript>$html_action</noscript>";
			$css = file_get_contents(find_in_path('css/nospam-checkbox.min.css'));
			$html_action .= "<style type='text/css'>$css</style>";
			break;

	}

	// supprimer des actions plus vieilles que 5mn en les logeant
	// si on le fait qu'a l'exec d'action legitime, on risque le flood si y a que des spammeurs !
	$old_time = $_SERVER['REQUEST_TIME'] - 5 * 60;
	nospam_purge_actions($dir_actions, ['mtime' => $old_time, 'limit' => 10]);

	return $html_action;
}


/**
 * Calculer un hash pour une action donnee
 *
 * @param $desc_json
 * @return bool|string
 */
function nospam_hash_action($desc_json) {
	if (!function_exists('secret_du_site')) {
		include_spip('inc/securiser_action');
	}
	$hash = substr(md5(__FILE__ . secret_du_site() . $desc_json), 0, 16);

	return $hash;
}


/**
 * Purge le répertoire des actions en logant tout ce qu'on purge
 *
 * @param string $dir
 *     Chemin du répertoire à purger
 * @param array $options
 *     Tableau des options. Peut être :
 *
 *     - atime : timestamp pour ne supprimer que les fichiers antérieurs
 *       à cette date (via fileatime)
 *     - mtime : timestamp pour ne supprimer que les fichiers antérieurs
 *       à cette date (via filemtime)
 *     - limit : nombre maximum de suppressions
 * @return int
 *     Nombre de fichiers supprimés
 **/
function nospam_purge_actions($dir, $options = array()) {
	if (!is_dir($dir) or !is_readable($dir)) {
		return;
	}
	$handle = opendir($dir);
	if (!$handle) {
		return;
	}

	$total = 0;

	while (($fichier = @readdir($handle)) !== false) {
		// Eviter ".", "..", ".htaccess", ".svn" etc.
		if ($fichier[0] == '.') {
			continue;
		}
		$chemin = "$dir/$fichier";
		if (is_file($chemin)) {
			if ((!isset($options['atime']) or (@fileatime($chemin) < $options['atime']))
				and (!isset($options['mtime']) or (@filemtime($chemin) < $options['mtime']))
			) {
				$action = file_get_contents($chemin);
				spip_log("Purge action non confirmee $fichier: $action", 'nospam_unconfirmed' . _LOG_INFO_IMPORTANTE);
				@unlink($chemin);
				$total++;
			}
		} else {
			if (is_dir($chemin)) {
				$opts = $options;
				if (isset($options['limit'])) {
					$opts['limit'] = $options['limit'] - $total;
				}
				$total += nospam_purge_actions($chemin, $opts);
				if (isset($options['subdir']) && $options['subdir']) {
					spip_unlink($chemin);
				}
			}
		}

		if (isset($options['limit']) and $total >= $options['limit']) {
			break;
		}
	}
	closedir($handle);

	return $total;
}