<?php
declare(strict_types = 1);

/**
 * Gestion des requêtes Ajax.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class Ajax
{
	/**
	 * Envoie la liste complète des émojis.
	 *
	 * @return void
	 */
	public static function getEmojis()
	{
		$list = Emoji::getList();
		$list['smileys_emotion']['list'] = [];
		self::_printResponse([
			'status' => 'success',
			'emojis' => $list
		]);
	}

	/**
	 * Initialisation.
	 *
	 * @param bool $admin
	 *   La requête ajax est-elle exécutée depuis l'administration ?
	 * @param bool $user_must_register
	 *   L'utilisateur doit-il être enregistré ?
	 *
	 * @return void
	 */
	public static function init(bool $from_admin = FALSE, bool $must_registered = TRUE): void
	{
		if ($from_admin)
		{
			App::$scriptName = 'admin';
			App::$scriptPath = '/' . CONF_ADMIN_DIR . '/';
		}

		// Connexion à la base de données.
		if (!DB::connect())
		{
			self::_printResponse(
			[
				'status' => 'error',
				'message' => 'Unable to connect to database.'
			]);
		}

		// Récupération de la configuration.
		Config::getDBParams();

		// Galerie fermée ?
		if (!$from_admin && Config::$params['gallery_closed'])
		{
			self::_forbidden();
		}

		// Authentification de l'utilisateur.
		Auth::cookie();

		// Si non authentifié.
		if (!Auth::$connected)
		{
			// Accès à l'admin interdit pour les invités
			// ou pour les actions nécessitant d'être enregistré.
			if ($must_registered || $from_admin)
			{
				self::_forbidden();
			}

			// Accès à la galerie interdit pour les invités ?
			if ($_POST['section'] != 'login'
			&& !$from_admin && Config::$params['users']
			&& Config::$params['users_only_members'])
			{
				self::_forbidden();
			}
		}

		// Actions admin.
		if ($from_admin && !Auth::$isAdmin)
		{
			self::_forbidden();
		}

		// Localisation.
		L10N::locale(!Auth::$connected && Config::$params['lang_switch']
			? Auth::$prefs->read('lang')
			: '');

		// Fichiers à activer ou désactiver.
		Item::pubexp();

		// Opérations quotidiennes.
		App::dailyUpdate();
	}

	/**
	 * Déconnexion d'un compte utilisateur ou d'une catégorie.
	 *
	 * @return void
	 */
	public static function logout(): void
	{
		$_POST['logout'] = 1;

		if ($_POST['from_admin'] && Auth::$connected && Auth::$isAdmin)
		{
			require_once(__DIR__ . '/admin/classes/AdminConnection.class.php');
			if (!AdminConnection::logout())
			{
				self::_printResponse([
					'status' => 'error',
					'message' => 'Logout error.'
				]);
			}
			$r = 'login';
		}
		else
		{
			if (!Utility::checkPost('id', '`^\d{1,12}$`'))
			{
				self::_forbidden();
			}

			require_once(__DIR__ . '/gallery/classes/GalleryUsers.class.php');
			$r = GalleryUsers::logout((int) $_POST['id']);

			if ($r === -1)
			{
				self::_printResponse([
					'status' => 'error',
					'message' => 'Database error.'
				]);
			}
			if ($r === 0)
			{
				self::_forbidden();
			}
			if ($r === 1)
			{
				self::_printResponse([
					'status' => 'error',
					'message' => 'Already disconnected.'
				]);
			}
		}

		self::_printResponse([
			'status' => 'success',
			'redirect' => App::getURL($r)
		]);
	}

	/**
	 * Récupère, vérifie et enregistre un fichier
	 * dans le répertoire des albums.
	 *
	 * @return void
	 */
	public static function uploadFile(): void
	{
		// Vérifications.
		if (!Auth::$groupPerms['upload']
		 || !isset($_POST['album_id']) || (int) $_POST['album_id'] < 2
		 || !isset($_POST['filename']) || !isset($_FILES['filedata'])
		 || !Utility::checkPost('from_admin', '`^[01]$`')
		 || !Utility::checkPost('last_part', '`^[01]$`')
		 || !Utility::checkPost('temp_dir', '`^[a-z\d]{40}$`i'))
		{
			self::_forbidden();
		}

		// On décode et filtre le nom de fichier.
		$_POST['filename'] = Utility::UTF8($_POST['filename']);
		$file_name = rawurldecode($_POST['filename']);
		$file_name = strstr($file_name, '?') ? $_POST['filename'] : $file_name;
		$file_name = preg_replace('`[\x5c/\?]`', '', $file_name);

		// Types de fichiers autorisés.
		switch (Auth::$groupPerms['upload_type'])
		{
			case 'images' :
				$file_exts = Image::EXT_ARRAY;
				$file_types = Item::IMAGE_TYPES;
				break;

			case 'videos' :
				$file_exts = Video::EXT_ARRAY;
				$file_types = Item::VIDEO_TYPES;
				break;

			default :
				$file_exts = array_merge_recursive(Video::EXT_ARRAY, Image::EXT_ARRAY);
				$file_types = array_merge_recursive(Item::VIDEO_TYPES, Item::IMAGE_TYPES);
		}

		// Vérification de l'extension du fichier.
		if (!preg_match('`.\.(' . implode('|', $file_exts) . ')$`i', $file_name, $m))
		{
			self::_forbidden();
		}
		$file_extension = strtolower($m[1]);

		// Paramètres SQL.
		$i = Category::getInfosUpload((int) $_POST['album_id'], (bool) $_POST['from_admin']);
		if ($i === FALSE)
		{
			self::_error();
		}
		if ($i === [])
		{
			self::_forbidden();
		}
		$cat_path = $i['cat_path'];

		// Si le répertoire temporaire d'upload n'existe pas, on le crée.
		$temp_dir = GALLERY_ROOT . '/cache/temp/' . $_POST['temp_dir'];
		if (!is_dir($temp_dir))
		{
			File::mkdir($temp_dir);
		}

		// Nom de fichier temporaire.
		$temp_file_path = $temp_dir . '/' . $file_name;

		// On récupère les données du fichier
		// et on l'enregistre dans le répertoire temporaire.
		if ($error = Upload::error($_FILES['filedata']))
		{
			self::_printResponse([
				'status' => 'warning',
				'message' => $error['text'],
				'filename' => $file_name
			]);
		}
		$data = file_get_contents($_FILES['filedata']['tmp_name'], TRUE);
		File::putContents($temp_file_path, $data, FILE_APPEND);

		// Dernière partie du fichier ?
		if ($_POST['last_part'] != 1)
		{
			goto file_ok;
		}

		// Vérifications du fichier.
		$verify = Upload::itemVerify($temp_file_path);
		if ($verify['error'])
		{
			self::_printResponse([
				'status' => 'warning',
				'message' => $verify['message'],
				'filename' => $file_name
			]);
		}

		// Redimensionnement de l'image.
		if ($verify['infos']['type'] == 'image'
		&& $error_msg = Upload::itemResize($temp_file_path))
		{
			self::_printResponse([
				'status' => 'error',
				'message' => $error_msg,
				'filename' => $file_name
			]);
		}

		// Tout est OK.
		file_ok:
		self::_printResponse([
			'status' => 'success',
			'message' => 'OK.',
			'filename' => $file_name
		]);
	}



	/**
	 * Erreur.
	 *
	 * @return void
	 */
	protected static function _error(): void
	{
		self::_printResponse([
			'status' => 'error',
			'message' => Report::getErrorDefaultMessage()
		]);
	}

	/**
	 * Accès interdit.
	 *
	 * @return void
	 */
	protected static function _forbidden(): void
	{
		$line = '[' . (int) debug_backtrace()[0]['line'] . '] ';
		self::_printResponse([
			'status' => 'error',
			'message' => $line . __('Accès interdit.')
		]);
	}

	/**
	 * Aucun changement.
	 *
	 * @return void
	 */
	protected static function _noChange(): void
	{
		self::_printResponse(
		[
			'status' => 'info',
			'message' => Report::getNoChangeDefaultMessage()
		]);
	}

	/**
	 * Réponse au format JSON.
	 *
	 * @param array $response
	 *
	 * @return void
	 */
	protected static function _printResponse(array $response): void
	{
		header('Content-Type: application/json; charset=' . CONF_CHARSET);
		die(Utility::jsonEncode($response));
	}

	/**
	 * Succès.
	 *
	 * @return void
	 */
	protected static function _success(): void
	{
		self::_printResponse(
		[
			'status' => 'success',
			'message' => Report::getSuccessDefaultMessage()
		]);
	}
}
?>