Skip to content
Extraits de code Groupes Projets
documents.php 8,39 ko
Newer Older
JamesRezo's avatar
JamesRezo a validé
/**
 * SPIP, Système de publication pour l'internet
 *
 * Copyright © avec tendresse depuis 2001
 * Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James
 *
 * Ce programme est un logiciel libre distribué sous licence GNU/GPL.
 */
Fil's avatar
Fil a validé

amemo's avatar
amemo a validé
/**
 * Gestion des documents et de leur emplacement sur le serveur
amemo's avatar
amemo a validé
 * @package SPIP\Core\Documents
 */

if (!defined('_ECRIRE_INC_VERSION')) {
	return;
}
cerdic's avatar
cerdic a validé
/**
amemo's avatar
amemo a validé
 * Donne le chemin du fichier relatif à `_DIR_IMG`
 * pour stockage 'tel quel' dans la base de données
amemo's avatar
amemo a validé
 * @uses _DIR_IMG
cerdic's avatar
cerdic a validé
 * @param string $fichier
 * @return string
 */
function set_spip_doc(?string $fichier): string {
marcimat's avatar
marcimat a validé
	if ($fichier && str_starts_with($fichier, (string) _DIR_IMG)) {
		return substr($fichier, strlen((string) _DIR_IMG));
marcimat's avatar
marcimat a validé
	}
cerdic's avatar
cerdic a validé
/**
amemo's avatar
amemo a validé
 * Donne le chemin complet du fichier
amemo's avatar
amemo a validé
 * @uses _DIR_IMG
cerdic's avatar
cerdic a validé
 *
 * @param string $fichier
 * @return bool|string
 */
kent1's avatar
kent1 a validé

marcimat's avatar
marcimat a validé
	if (!str_starts_with($fichier, (string) _DIR_IMG)) {
	
	$fichier = pipeline('get_spip_doc', ['args' => ['fichier' => $fichier_demande], 'data' => $fichier]);
cerdic's avatar
cerdic a validé
	return $fichier;
cerdic's avatar
cerdic a validé
/**
amemo's avatar
amemo a validé
 * Créer un sous-répertoire IMG/$ext/ tel que IMG/pdf
amemo's avatar
amemo a validé
 * @uses sous_repertoire()
 * @uses _DIR_IMG
 * @uses verifier_htaccess()
amemo's avatar
amemo a validé
 * @param string $ext
cerdic's avatar
cerdic a validé
 * @return string
 */
function creer_repertoire_documents($ext) {
	$rep = sous_repertoire(_DIR_IMG, $ext);
marcimat's avatar
marcimat a validé
	if (!$ext || !$rep) {
		spip_logger()->info("creer_repertoire_documents '$rep' interdit");
cerdic's avatar
cerdic a validé
		exit;
cerdic's avatar
cerdic a validé
	}
kent1's avatar
kent1 a validé

cerdic's avatar
cerdic a validé
	// Cette variable de configuration peut etre posee par un plugin
	// par exemple acces_restreint
	// sauf pour logo/ utilise pour stocker les logoon et logooff
JamesRezo's avatar
JamesRezo a validé
	if (
		isset($GLOBALS['meta']['creer_htaccess'])
marcimat's avatar
marcimat a validé
		&& $GLOBALS['meta']['creer_htaccess'] == 'oui'
		&& $ext !== 'logo'
JamesRezo's avatar
JamesRezo a validé
	) {
cerdic's avatar
cerdic a validé
		include_spip('inc/acces');
		verifier_htaccess($rep);
cerdic's avatar
cerdic a validé
	return $rep;
cerdic's avatar
cerdic a validé
/**
amemo's avatar
amemo a validé
 * Efface le répertoire de manière récursive !
cerdic's avatar
cerdic a validé
 *
 * @param string $nom
 */
function effacer_repertoire_temporaire($nom) {
	if ($d = opendir($nom)) {
		while (($f = readdir($d)) !== false) {
			if (is_file("$nom/$f")) {
				spip_unlink("$nom/$f");
			} else {
marcimat's avatar
marcimat a validé
				if ($f != '.' && $f != '..' && is_dir("$nom/$f")) {
cerdic's avatar
cerdic a validé
	}
	closedir($d);
	@rmdir($nom);
Fil's avatar
 
Fil a validé
//
cerdic's avatar
cerdic a validé
/**
 * Copier un document `$source`
 * dans un dossier `IMG/$ext/$orig.$ext` ou `IMG/$subdir/$orig.$ext` si `$subdir` est fourni
amemo's avatar
amemo a validé
 * en numérotant éventuellement si un fichier de même nom existe déjà
cerdic's avatar
cerdic a validé
 *
 * @param string $ext
 * @param string $orig
 * @param string $source
cerdic's avatar
cerdic a validé
 * @return bool|mixed|string
 */
function copier_document($ext, $orig, $source, $subdir = null) {
cerdic's avatar
cerdic a validé

	$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
	$dir = creer_repertoire_documents($subdir ?: $ext);

	$dest = preg_replace('/<[^>]*>/', '', basename($orig));
marcimat's avatar
marcimat a validé
	$dest = preg_replace('/\.([^.]+)$/', '', $dest);
	$dest = translitteration($dest);
marcimat's avatar
marcimat a validé
	$dest = preg_replace('/[^.=\w-]+/', '_', (string) $dest);
cerdic's avatar
cerdic a validé

	// ne pas accepter de noms de la forme -r90.jpg qui sont reserves
	// pour les images transformees par rotation (action/documenter)
	$dest = preg_replace(',-r(90|180|270)$,', '', $dest);

marcimat's avatar
marcimat a validé
	while (preg_match(',\.(\w+)$,', $dest, $m)) {
		if (
			!function_exists('verifier_upload_autorise')
marcimat's avatar
marcimat a validé
			|| !($r = verifier_upload_autorise($dest))
			|| !empty($r['autozip'])
marcimat's avatar
marcimat a validé
		) {
			$dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
			break;
marcimat's avatar
marcimat a validé
		} else {
			$dest = substr($dest, 0, -strlen($m[0]));
marcimat's avatar
marcimat a validé
			$ext = $m[1] . '.' . $ext;
cerdic's avatar
cerdic a validé
	// Si le document "source" est deja au bon endroit, ne rien faire
	if ($source == ($dir . $dest . '.' . $ext)) {
cerdic's avatar
cerdic a validé
		return $source;
cerdic's avatar
cerdic a validé

	// sinon tourner jusqu'a trouver un numero correct
	$n = 0;
	while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
		;
	}
cerdic's avatar
cerdic a validé

	return deplacer_fichier_upload($source, $newFile);
Fil's avatar
 
Fil a validé
}
amemo's avatar
amemo a validé
 * Trouver le dossier utilisé pour upload un fichier
amemo's avatar
amemo a validé
 * @uses autoriser()
 * @uses _DIR_TRANSFERT
 * @uses _DIR_TMP
 * @uses sous_repertoire()
 * @param string $type
 * @return bool|string
 */
JamesRezo's avatar
JamesRezo a validé
	if (
		!autoriser('chargerftp')
marcimat's avatar
marcimat a validé
		|| $type == 'logos'
JamesRezo's avatar
JamesRezo a validé
	) { # on ne le permet pas pour les logos
	return false;

	$repertoire = _DIR_TRANSFERT;
	if (!@is_dir($repertoire)) {
marcimat's avatar
marcimat a validé
		$repertoire = str_replace(_DIR_TMP, '', (string) $repertoire);
		$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
	}

	if (!$GLOBALS['visiteur_session']['restreint']) {
		return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
cerdic's avatar
cerdic a validé
/**
amemo's avatar
amemo a validé
 * Déplacer ou copier un fichier
amemo's avatar
amemo a validé
 * @uses _DIR_RACINE
 * @uses spip_unlink()
cerdic's avatar
cerdic a validé
 * @param string $source
amemo's avatar
amemo a validé
 *     Fichier source à copier
cerdic's avatar
cerdic a validé
 * @param string $dest
amemo's avatar
amemo a validé
 *     Fichier de destination
cerdic's avatar
cerdic a validé
 * @param bool $move
amemo's avatar
amemo a validé
 *     - `true` : on déplace le fichier source vers le fichier de destination
 *     - `false` : valeur par défaut. On ne fait que copier le fichier source vers la destination.
cerdic's avatar
cerdic a validé
 * @return bool|mixed|string
 */
function deplacer_fichier_upload($source, $dest, $move = false) {
cerdic's avatar
cerdic a validé
	// Securite
marcimat's avatar
marcimat a validé
	if (str_starts_with($dest, (string) _DIR_RACINE)) {
		$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen((string) _DIR_RACINE)));
cerdic's avatar
cerdic a validé
		$dest = preg_replace(',\.\.+,', '.', $dest);
marcimat's avatar
marcimat a validé
	$ok = $move ? @rename($source, $dest) : @copy($source, $dest);
	if (!$ok) {
		$ok = @move_uploaded_file($source, $dest);
	}
	if ($ok) {
cerdic's avatar
cerdic a validé
		@chmod($dest, _SPIP_CHMOD & ~0111);
cerdic's avatar
cerdic a validé
		if ($f) {
cerdic's avatar
cerdic a validé
		} else {
			include_spip('inc/flock');
			raler_fichier($dest);
cerdic's avatar
cerdic a validé
		spip_unlink($dest);
cerdic's avatar
cerdic a validé
	return $ok ? $dest : false;
amemo's avatar
amemo a validé
/**
 * Erreurs d'upload
 *
 * Renvoie `false` si pas d'erreur
 * et `true` s'il n'y a pas de fichier à uploader.
 * Pour les autres erreurs, on affiche le message d'erreur et on arrête l'action.
 *
 * @link http://php.net/manual/fr/features.file-upload.errors.php
amemo's avatar
amemo a validé
 *     Explication sur les messages d'erreurs de chargement de fichiers.
 * @uses propre()
 * @uses minipres()
amemo's avatar
amemo a validé
 * @global string $spip_lang_right
 * @param integer $error
 * @param string $msg
 * @param bool $return
 * @return boolean|string
 */
function check_upload_error($error, $msg = '', $return = false) {
	spip_logger()->info("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");

	switch ($error) {
		case 4: /* UPLOAD_ERR_NO_FILE */
			return true;

		# on peut affiner les differents messages d'erreur
		case 1: /* UPLOAD_ERR_INI_SIZE */
JamesRezo's avatar
JamesRezo a validé
			$msg = _T(
				'upload_limit',
				['max' => ini_get('upload_max_filesize')]
			);
			break;
		case 2: /* UPLOAD_ERR_FORM_SIZE */
JamesRezo's avatar
JamesRezo a validé
			$msg = _T(
				'upload_limit',
				['max' => ini_get('upload_max_filesize')]
			);
			break;
		case 3: /* UPLOAD_ERR_PARTIAL  */
JamesRezo's avatar
JamesRezo a validé
			$msg = _T(
				'upload_limit',
				['max' => ini_get('upload_max_filesize')]
			);
			if (!$msg) {
				$msg = _T('pass_erreur') . ' ' . $error
					. '<br>' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
	spip_logger()->info("erreur upload $error");
JamesRezo's avatar
JamesRezo a validé
	if (_request('iframe') == 'iframe') {
		echo "<div class='upload_answer upload_error'>$msg</div>";
		exit;
cerdic's avatar
cerdic a validé
	include_spip('inc/minipres');
JamesRezo's avatar
JamesRezo a validé
	echo minipres(
		$msg,
		"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . attribut_url(rawurldecode((string) $GLOBALS['redirect'])) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
JamesRezo's avatar
JamesRezo a validé
	);

/**
 * Corrige l'extension du fichier dans quelques cas particuliers
 *
 * @note
 *     Une extension 'pdf ' passe dans la requête de contrôle
 *     mysql> SELECT * FROM spip_types_documents WHERE extension="pdf ";
 *
 * @todo
 *     À passer dans base/typedoc
 *
 * @param string $ext
 * @return string
 */
function corriger_extension($ext) {
	$ext = preg_replace(',[^a-z0-9],i', '', $ext);

marcimat's avatar
marcimat a validé
	return match ($ext) {
		'htm' => 'html',
		'jpeg' => 'jpg',
		'tiff' => 'tif',
		'aif' => 'aiff',
		'mpeg' => 'mpg',
		default => $ext,
	};
b_b's avatar
b_b a validé
}