[SPIP] v3.2.11 -> v3.2.12
[lhc/web/www.git] / www / ecrire / inc / documents.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Gestion des documents et de leur emplacement sur le serveur
15 *
16 * @package SPIP\Core\Documents
17 */
18
19 if (!defined('_ECRIRE_INC_VERSION')) {
20 return;
21 }
22
23 /**
24 * Donne le chemin du fichier relatif à `_DIR_IMG`
25 * pour stockage 'tel quel' dans la base de données
26 *
27 * @uses _DIR_IMG
28 *
29 * @param string $fichier
30 * @return string
31 */
32 function set_spip_doc($fichier) {
33 if (strpos($fichier, _DIR_IMG) === 0) {
34 return substr($fichier, strlen(_DIR_IMG));
35 } else {
36 return $fichier;
37 } // ex: fichier distant
38 }
39
40 /**
41 * Donne le chemin complet du fichier
42 *
43 * @uses _DIR_IMG
44 *
45 * @param string $fichier
46 * @return bool|string
47 */
48 function get_spip_doc($fichier) {
49 // fichier distant
50 if (tester_url_absolue($fichier)) {
51 return $fichier;
52 }
53
54 // gestion d'erreurs, fichier=''
55 if (!strlen($fichier)) {
56 return false;
57 }
58
59 $fichier = (
60 strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) != 0
61 )
62 ? _DIR_IMG . $fichier
63 : $fichier;
64
65 // fichier normal
66 return $fichier;
67 }
68
69 /**
70 * Créer un sous-répertoire IMG/$ext/ tel que IMG/pdf
71 *
72 * @uses sous_repertoire()
73 * @uses _DIR_IMG
74 * @uses verifier_htaccess()
75 *
76 * @param string $ext
77 * @return string
78 */
79 function creer_repertoire_documents($ext) {
80 $rep = sous_repertoire(_DIR_IMG, $ext);
81
82 if (!$ext or !$rep) {
83 spip_log("creer_repertoire_documents '$rep' interdit");
84 exit;
85 }
86
87 // Cette variable de configuration peut etre posee par un plugin
88 // par exemple acces_restreint
89 if (isset($GLOBALS['meta']["creer_htaccess"]) and $GLOBALS['meta']["creer_htaccess"] == 'oui') {
90 include_spip('inc/acces');
91 verifier_htaccess($rep);
92 }
93
94 return $rep;
95 }
96
97 /**
98 * Efface le répertoire de manière récursive !
99 *
100 * @param string $nom
101 */
102 function effacer_repertoire_temporaire($nom) {
103 if ($d = opendir($nom)) {
104 while (($f = readdir($d)) !== false) {
105 if (is_file("$nom/$f")) {
106 spip_unlink("$nom/$f");
107 } else {
108 if ($f <> '.' and $f <> '..'
109 and is_dir("$nom/$f")
110 ) {
111 effacer_repertoire_temporaire("$nom/$f");
112 }
113 }
114 }
115 }
116 closedir($d);
117 @rmdir($nom);
118 }
119
120 //
121 /**
122 * Copier un document `$source` un dossier `IMG/$ext/$orig.$ext`
123 * en numérotant éventuellement si un fichier de même nom existe déjà
124 *
125 * @param string $ext
126 * @param string $orig
127 * @param string $source
128 * @return bool|mixed|string
129 */
130 function copier_document($ext, $orig, $source) {
131
132 $orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
133 $dir = creer_repertoire_documents($ext);
134 $dest = preg_replace("/[^.=\w-]+/", "_",
135 translitteration(preg_replace("/\.([^.]+)$/", "",
136 preg_replace("/<[^>]*>/", '', basename($orig)))));
137
138 // ne pas accepter de noms de la forme -r90.jpg qui sont reserves
139 // pour les images transformees par rotation (action/documenter)
140 $dest = preg_replace(',-r(90|180|270)$,', '', $dest);
141
142 while (preg_match(",\.(\w+)$,", $dest, $m)) {
143 if (!function_exists('verifier_upload_autorise')
144 or !$r = verifier_upload_autorise($dest)
145 or $r['autozip']) {
146 $dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
147 break;
148 }
149 else {
150 $dest = substr($dest, 0, -strlen($m[0]));
151 $ext = $m[1] . "." . $ext;
152 }
153 }
154
155 // Si le document "source" est deja au bon endroit, ne rien faire
156 if ($source == ($dir . $dest . '.' . $ext)) {
157 return $source;
158 }
159
160 // sinon tourner jusqu'a trouver un numero correct
161 $n = 0;
162 while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
163 ;
164 }
165
166 return deplacer_fichier_upload($source, $newFile);
167 }
168
169 /**
170 * Trouver le dossier utilisé pour upload un fichier
171 *
172 * @uses autoriser()
173 * @uses _DIR_TRANSFERT
174 * @uses _DIR_TMP
175 * @uses sous_repertoire()
176 *
177 * @param string $type
178 * @return bool|string
179 */
180 function determine_upload($type = '') {
181 if (!function_exists('autoriser')) {
182 include_spip('inc/autoriser');
183 }
184
185 if (!autoriser('chargerftp')
186 or $type == 'logos'
187 ) # on ne le permet pas pour les logos
188 {
189 return false;
190 }
191
192 $repertoire = _DIR_TRANSFERT;
193 if (!@is_dir($repertoire)) {
194 $repertoire = str_replace(_DIR_TMP, '', $repertoire);
195 $repertoire = sous_repertoire(_DIR_TMP, $repertoire);
196 }
197
198 if (!$GLOBALS['visiteur_session']['restreint']) {
199 return $repertoire;
200 } else {
201 return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
202 }
203 }
204
205 /**
206 * Déplacer ou copier un fichier
207 *
208 * @uses _DIR_RACINE
209 * @uses spip_unlink()
210 *
211 * @param string $source
212 * Fichier source à copier
213 * @param string $dest
214 * Fichier de destination
215 * @param bool $move
216 * - `true` : on déplace le fichier source vers le fichier de destination
217 * - `false` : valeur par défaut. On ne fait que copier le fichier source vers la destination.
218 * @return bool|mixed|string
219 */
220 function deplacer_fichier_upload($source, $dest, $move = false) {
221 // Securite
222 if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
223 $dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
224 } else {
225 $dest = preg_replace(',\.\.+,', '.', $dest);
226 }
227
228 if ($move) {
229 $ok = @rename($source, $dest);
230 } else {
231 $ok = @copy($source, $dest);
232 }
233 if (!$ok) {
234 $ok = @move_uploaded_file($source, $dest);
235 }
236 if ($ok) {
237 @chmod($dest, _SPIP_CHMOD & ~0111);
238 } else {
239 $f = @fopen($dest, 'w');
240 if ($f) {
241 fclose($f);
242 } else {
243 include_spip('inc/flock');
244 raler_fichier($dest);
245 }
246 spip_unlink($dest);
247 }
248
249 return $ok ? $dest : false;
250 }
251
252
253 /**
254 * Erreurs d'upload
255 *
256 * Renvoie `false` si pas d'erreur
257 * et `true` s'il n'y a pas de fichier à uploader.
258 * Pour les autres erreurs, on affiche le message d'erreur et on arrête l'action.
259 *
260 * @link http://php.net/manual/fr/features.file-upload.errors.php
261 * Explication sur les messages d'erreurs de chargement de fichiers.
262 * @uses propre()
263 * @uses minipres()
264 *
265 * @global string $spip_lang_right
266 * @param integer $error
267 * @param string $msg
268 * @param bool $return
269 * @return boolean|string
270 */
271 function check_upload_error($error, $msg = '', $return = false) {
272
273 if (!$error) {
274 return false;
275 }
276
277 spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
278
279 switch ($error) {
280
281 case 4: /* UPLOAD_ERR_NO_FILE */
282 return true;
283
284 # on peut affiner les differents messages d'erreur
285 case 1: /* UPLOAD_ERR_INI_SIZE */
286 $msg = _T('upload_limit',
287 array('max' => ini_get('upload_max_filesize')));
288 break;
289 case 2: /* UPLOAD_ERR_FORM_SIZE */
290 $msg = _T('upload_limit',
291 array('max' => ini_get('upload_max_filesize')));
292 break;
293 case 3: /* UPLOAD_ERR_PARTIAL */
294 $msg = _T('upload_limit',
295 array('max' => ini_get('upload_max_filesize')));
296 break;
297
298 default: /* autre */
299 if (!$msg) {
300 $msg = _T('pass_erreur') . ' ' . $error
301 . '<br />' . propre("[->http://php.net/manual/fr/features.file-upload.errors.php]");
302 }
303 break;
304 }
305
306 spip_log("erreur upload $error");
307 if ($return) {
308 return $msg;
309 }
310
311 if (_request("iframe") == "iframe") {
312 echo "<div class='upload_answer upload_error'>$msg</div>";
313 exit;
314 }
315
316 include_spip('inc/minipres');
317 echo minipres($msg,
318 "<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . "</button></a></div>");
319 exit;
320 }