Completed
Push — master ( 323572...565410 )
by cam
04:16
created

documents.php ➔ creer_repertoire_documents()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 3
nop 1
dl 0
loc 20
rs 8.9777
c 0
b 0
f 0
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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
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
	// sauf pour logo/ utilise pour stocker les logoon et logooff
90
	if (isset($GLOBALS['meta']["creer_htaccess"])
91
		and $GLOBALS['meta']["creer_htaccess"] == 'oui'
92
	  and $ext !== 'logo') {
93
		include_spip('inc/acces');
94
		verifier_htaccess($rep);
95
	}
96
97
	return $rep;
98
}
99
100
/**
101
 * Efface le répertoire de manière récursive !
102
 *
103
 * @param string $nom
104
 */
105
function effacer_repertoire_temporaire($nom) {
106
	if ($d = opendir($nom)) {
107
		while (($f = readdir($d)) !== false) {
108
			if (is_file("$nom/$f")) {
109
				spip_unlink("$nom/$f");
110
			} else {
111
				if ($f <> '.' and $f <> '..'
112
					and is_dir("$nom/$f")
113
				) {
114
					effacer_repertoire_temporaire("$nom/$f");
115
				}
116
			}
117
		}
118
	}
119
	closedir($d);
120
	@rmdir($nom);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
121
}
122
123
//
124
/**
125
 * Copier un document `$source`
126
 * dans un dossier `IMG/$ext/$orig.$ext` ou `IMG/$subdir/$orig.$ext` si `$subdir` est fourni
127
 * en numérotant éventuellement si un fichier de même nom existe déjà
128
 *
129
 * @param string $ext
130
 * @param string $orig
131
 * @param string $source
132
 * @param string $subdir
0 ignored issues
show
Documentation introduced by
Should the type for parameter $subdir not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
133
 * @return bool|mixed|string
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
134
 */
135
function copier_document($ext, $orig, $source, $subdir = null) {
136
137
	$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
138
	$dir = creer_repertoire_documents($subdir ? $subdir : $ext);
139
	$dest = preg_replace("/[^.=\w-]+/", "_",
140
		translitteration(preg_replace("/\.([^.]+)$/", "",
141
			preg_replace("/<[^>]*>/", '', basename($orig)))));
142
143
	// ne pas accepter de noms de la forme -r90.jpg qui sont reserves
144
	// pour les images transformees par rotation (action/documenter)
145
	$dest = preg_replace(',-r(90|180|270)$,', '', $dest);
146
147
	// Si le document "source" est deja au bon endroit, ne rien faire
148
	if ($source == ($dir . $dest . '.' . $ext)) {
149
		return $source;
150
	}
151
152
	// sinon tourner jusqu'a trouver un numero correct
153
	$n = 0;
154
	while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
155
		;
156
	}
157
158
	return deplacer_fichier_upload($source, $newFile);
159
}
160
161
/**
162
 * Trouver le dossier utilisé pour upload un fichier
163
 *
164
 * @uses autoriser()
165
 * @uses _DIR_TRANSFERT
166
 * @uses _DIR_TMP
167
 * @uses sous_repertoire()
168
 *
169
 * @param string $type
170
 * @return bool|string
0 ignored issues
show
Documentation introduced by
Should the return type not be false|string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
171
 */
172
function determine_upload($type = '') {
173
	if (!function_exists('autoriser')) {
174
		include_spip('inc/autoriser');
175
	}
176
177
	if (!autoriser('chargerftp')
178
		or $type == 'logos'
179
	) # on ne le permet pas pour les logos
180
	{
181
		return false;
182
	}
183
184
	$repertoire = _DIR_TRANSFERT;
185 View Code Duplication
	if (!@is_dir($repertoire)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
		$repertoire = str_replace(_DIR_TMP, '', $repertoire);
187
		$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
188
	}
189
190
	if (!$GLOBALS['visiteur_session']['restreint']) {
191
		return $repertoire;
192
	} else {
193
		return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
194
	}
195
}
196
197
/**
198
 * Déplacer ou copier un fichier
199
 *
200
 * @uses _DIR_RACINE
201
 * @uses spip_unlink()
202
 *
203
 * @param string $source
204
 *     Fichier source à copier
205
 * @param string $dest
206
 *     Fichier de destination
207
 * @param bool $move
208
 *     - `true` : on déplace le fichier source vers le fichier de destination
209
 *     - `false` : valeur par défaut. On ne fait que copier le fichier source vers la destination.
210
 * @return bool|mixed|string
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
211
 */
212
function deplacer_fichier_upload($source, $dest, $move = false) {
213
	// Securite
214
	if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
215
		$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
216
	} else {
217
		$dest = preg_replace(',\.\.+,', '.', $dest);
218
	}
219
220
	if ($move) {
221
		$ok = @rename($source, $dest);
222
	} else {
223
		$ok = @copy($source, $dest);
224
	}
225
	if (!$ok) {
226
		$ok = @move_uploaded_file($source, $dest);
227
	}
228
	if ($ok) {
229
		@chmod($dest, _SPIP_CHMOD & ~0111);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
230
	} else {
231
		$f = @fopen($dest, 'w');
232
		if ($f) {
233
			fclose($f);
234
		} else {
235
			include_spip('inc/flock');
236
			raler_fichier($dest);
237
		}
238
		spip_unlink($dest);
239
	}
240
241
	return $ok ? $dest : false;
242
}
243
244
245
/**
246
 * Erreurs d'upload
247
 *
248
 * Renvoie `false` si pas d'erreur
249
 * et `true` s'il n'y a pas de fichier à uploader.
250
 * Pour les autres erreurs, on affiche le message d'erreur et on arrête l'action.
251
 *
252
 * @link http://php.net/manual/fr/features.file-upload.errors.php
253
 *     Explication sur les messages d'erreurs de chargement de fichiers.
254
 * @uses propre()
255
 * @uses minipres()
256
 *
257
 * @global string $spip_lang_right
258
 * @param integer $error
259
 * @param string $msg
260
 * @param bool $return
261
 * @return boolean|string
262
 */
263
function check_upload_error($error, $msg = '', $return = false) {
264
265
	if (!$error) {
266
		return false;
267
	}
268
269
	spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
270
271
	switch ($error) {
272
273
		case 4: /* UPLOAD_ERR_NO_FILE */
274
			return true;
275
276
		# on peut affiner les differents messages d'erreur
277
		case 1: /* UPLOAD_ERR_INI_SIZE */
278
			$msg = _T('upload_limit',
279
				array('max' => ini_get('upload_max_filesize')));
280
			break;
281
		case 2: /* UPLOAD_ERR_FORM_SIZE */
282
			$msg = _T('upload_limit',
283
				array('max' => ini_get('upload_max_filesize')));
284
			break;
285
		case 3: /* UPLOAD_ERR_PARTIAL  */
286
			$msg = _T('upload_limit',
287
				array('max' => ini_get('upload_max_filesize')));
288
			break;
289
290
		default: /* autre */
291
			if (!$msg) {
292
				$msg = _T('pass_erreur') . ' ' . $error
293
					. '<br />' . propre("[->http://php.net/manual/fr/features.file-upload.errors.php]");
294
			}
295
			break;
296
	}
297
298
	spip_log("erreur upload $error");
299
	if ($return) {
300
		return $msg;
301
	}
302
303
	if (_request("iframe") == "iframe") {
304
		echo "<div class='upload_answer upload_error'>$msg</div>";
305
		exit;
306
	}
307
308
	include_spip('inc/minipres');
309
	echo minipres($msg,
310
		"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . "</button></a></div>");
311
	exit;
312
}
313