321 lines
7.8 KiB
PHP
321 lines
7.8 KiB
PHP
|
<?php
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* SPIP, Systeme de publication pour l'internet *
|
||
|
* *
|
||
|
* Copyright (c) 2001-2019 *
|
||
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
|
||
|
* *
|
||
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
|
||
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
|
||
|
\***************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* Gestion des documents et de leur emplacement sur le serveur
|
||
|
*
|
||
|
* @package SPIP\Core\Documents
|
||
|
*/
|
||
|
|
||
|
if (!defined('_ECRIRE_INC_VERSION')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Donne le chemin du fichier relatif à `_DIR_IMG`
|
||
|
* pour stockage 'tel quel' dans la base de données
|
||
|
*
|
||
|
* @uses _DIR_IMG
|
||
|
*
|
||
|
* @param string $fichier
|
||
|
* @return string
|
||
|
*/
|
||
|
function set_spip_doc($fichier) {
|
||
|
if (strpos($fichier, _DIR_IMG) === 0) {
|
||
|
return substr($fichier, strlen(_DIR_IMG));
|
||
|
} else {
|
||
|
return $fichier;
|
||
|
} // ex: fichier distant
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Donne le chemin complet du fichier
|
||
|
*
|
||
|
* @uses _DIR_IMG
|
||
|
*
|
||
|
* @param string $fichier
|
||
|
* @return bool|string
|
||
|
*/
|
||
|
function get_spip_doc($fichier) {
|
||
|
// fichier distant
|
||
|
if (tester_url_absolue($fichier)) {
|
||
|
return $fichier;
|
||
|
}
|
||
|
|
||
|
// gestion d'erreurs, fichier=''
|
||
|
if (!strlen($fichier)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$fichier = (
|
||
|
strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) != 0
|
||
|
)
|
||
|
? _DIR_IMG . $fichier
|
||
|
: $fichier;
|
||
|
|
||
|
// fichier normal
|
||
|
return $fichier;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Créer un sous-répertoire IMG/$ext/ tel que IMG/pdf
|
||
|
*
|
||
|
* @uses sous_repertoire()
|
||
|
* @uses _DIR_IMG
|
||
|
* @uses verifier_htaccess()
|
||
|
*
|
||
|
* @param string $ext
|
||
|
* @return string
|
||
|
*/
|
||
|
function creer_repertoire_documents($ext) {
|
||
|
$rep = sous_repertoire(_DIR_IMG, $ext);
|
||
|
|
||
|
if (!$ext or !$rep) {
|
||
|
spip_log("creer_repertoire_documents '$rep' interdit");
|
||
|
exit;
|
||
|
}
|
||
|
|
||
|
// Cette variable de configuration peut etre posee par un plugin
|
||
|
// par exemple acces_restreint
|
||
|
if (isset($GLOBALS['meta']["creer_htaccess"]) and $GLOBALS['meta']["creer_htaccess"] == 'oui') {
|
||
|
include_spip('inc/acces');
|
||
|
verifier_htaccess($rep);
|
||
|
}
|
||
|
|
||
|
return $rep;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Efface le répertoire de manière récursive !
|
||
|
*
|
||
|
* @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 {
|
||
|
if ($f <> '.' and $f <> '..'
|
||
|
and is_dir("$nom/$f")
|
||
|
) {
|
||
|
effacer_repertoire_temporaire("$nom/$f");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
closedir($d);
|
||
|
@rmdir($nom);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
/**
|
||
|
* Copier un document `$source` un dossier `IMG/$ext/$orig.$ext`
|
||
|
* en numérotant éventuellement si un fichier de même nom existe déjà
|
||
|
*
|
||
|
* @param string $ext
|
||
|
* @param string $orig
|
||
|
* @param string $source
|
||
|
* @return bool|mixed|string
|
||
|
*/
|
||
|
function copier_document($ext, $orig, $source) {
|
||
|
|
||
|
$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
|
||
|
$dir = creer_repertoire_documents($ext);
|
||
|
$dest = preg_replace("/[^.=\w-]+/", "_",
|
||
|
translitteration(preg_replace("/\.([^.]+)$/", "",
|
||
|
preg_replace("/<[^>]*>/", '', basename($orig)))));
|
||
|
|
||
|
// 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);
|
||
|
|
||
|
while (preg_match(",\.(\w+)$,", $dest, $m)) {
|
||
|
if (!function_exists('verifier_upload_autorise')
|
||
|
or !$r = verifier_upload_autorise($dest)
|
||
|
or $r['autozip']) {
|
||
|
$dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
$dest = substr($dest, 0, -strlen($m[0]));
|
||
|
$ext = $m[1] . "." . $ext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Si le document "source" est deja au bon endroit, ne rien faire
|
||
|
if ($source == ($dir . $dest . '.' . $ext)) {
|
||
|
return $source;
|
||
|
}
|
||
|
|
||
|
// sinon tourner jusqu'a trouver un numero correct
|
||
|
$n = 0;
|
||
|
while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
|
||
|
;
|
||
|
}
|
||
|
|
||
|
return deplacer_fichier_upload($source, $newFile);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Trouver le dossier utilisé pour upload un fichier
|
||
|
*
|
||
|
* @uses autoriser()
|
||
|
* @uses _DIR_TRANSFERT
|
||
|
* @uses _DIR_TMP
|
||
|
* @uses sous_repertoire()
|
||
|
*
|
||
|
* @param string $type
|
||
|
* @return bool|string
|
||
|
*/
|
||
|
function determine_upload($type = '') {
|
||
|
if (!function_exists('autoriser')) {
|
||
|
include_spip('inc/autoriser');
|
||
|
}
|
||
|
|
||
|
if (!autoriser('chargerftp')
|
||
|
or $type == 'logos'
|
||
|
) # on ne le permet pas pour les logos
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$repertoire = _DIR_TRANSFERT;
|
||
|
if (!@is_dir($repertoire)) {
|
||
|
$repertoire = str_replace(_DIR_TMP, '', $repertoire);
|
||
|
$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
|
||
|
}
|
||
|
|
||
|
if (!$GLOBALS['visiteur_session']['restreint']) {
|
||
|
return $repertoire;
|
||
|
} else {
|
||
|
return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Déplacer ou copier un fichier
|
||
|
*
|
||
|
* @uses _DIR_RACINE
|
||
|
* @uses spip_unlink()
|
||
|
*
|
||
|
* @param string $source
|
||
|
* Fichier source à copier
|
||
|
* @param string $dest
|
||
|
* Fichier de destination
|
||
|
* @param bool $move
|
||
|
* - `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.
|
||
|
* @return bool|mixed|string
|
||
|
*/
|
||
|
function deplacer_fichier_upload($source, $dest, $move = false) {
|
||
|
// Securite
|
||
|
if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
|
||
|
$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
|
||
|
} else {
|
||
|
$dest = preg_replace(',\.\.+,', '.', $dest);
|
||
|
}
|
||
|
|
||
|
if ($move) {
|
||
|
$ok = @rename($source, $dest);
|
||
|
} else {
|
||
|
$ok = @copy($source, $dest);
|
||
|
}
|
||
|
if (!$ok) {
|
||
|
$ok = @move_uploaded_file($source, $dest);
|
||
|
}
|
||
|
if ($ok) {
|
||
|
@chmod($dest, _SPIP_CHMOD & ~0111);
|
||
|
} else {
|
||
|
$f = @fopen($dest, 'w');
|
||
|
if ($f) {
|
||
|
fclose($f);
|
||
|
} else {
|
||
|
include_spip('inc/flock');
|
||
|
raler_fichier($dest);
|
||
|
}
|
||
|
spip_unlink($dest);
|
||
|
}
|
||
|
|
||
|
return $ok ? $dest : false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 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
|
||
|
* Explication sur les messages d'erreurs de chargement de fichiers.
|
||
|
* @uses propre()
|
||
|
* @uses minipres()
|
||
|
*
|
||
|
* @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) {
|
||
|
|
||
|
if (!$error) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
spip_log("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 */
|
||
|
$msg = _T('upload_limit',
|
||
|
array('max' => ini_get('upload_max_filesize')));
|
||
|
break;
|
||
|
case 2: /* UPLOAD_ERR_FORM_SIZE */
|
||
|
$msg = _T('upload_limit',
|
||
|
array('max' => ini_get('upload_max_filesize')));
|
||
|
break;
|
||
|
case 3: /* UPLOAD_ERR_PARTIAL */
|
||
|
$msg = _T('upload_limit',
|
||
|
array('max' => ini_get('upload_max_filesize')));
|
||
|
break;
|
||
|
|
||
|
default: /* autre */
|
||
|
if (!$msg) {
|
||
|
$msg = _T('pass_erreur') . ' ' . $error
|
||
|
. '<br />' . propre("[->http://php.net/manual/fr/features.file-upload.errors.php]");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
spip_log("erreur upload $error");
|
||
|
if ($return) {
|
||
|
return $msg;
|
||
|
}
|
||
|
|
||
|
if (_request("iframe") == "iframe") {
|
||
|
echo "<div class='upload_answer upload_error'>$msg</div>";
|
||
|
exit;
|
||
|
}
|
||
|
|
||
|
include_spip('inc/minipres');
|
||
|
echo minipres($msg,
|
||
|
"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . "</button></a></div>");
|
||
|
exit;
|
||
|
}
|