Completed
Push — master ( 4d844b...afe3a6 )
by cam
04:16
created

phpthumb_functions::LittleEndian2String()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 9
rs 9.9666
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
 * Ce fichier contient les fonctions utilisées
15
 * par les fonctions-filtres de traitement d'image.
16
 *
17
 * @package SPIP\Core\Filtres\Images
18
 */
19
20
21
if (!defined('_ECRIRE_INC_VERSION')) {
22
	return;
23
}
24
include_spip('inc/filtres'); // par precaution
25
include_spip('inc/filtres_images_mini'); // par precaution
26
27
define('_SVG_SUPPORTED', true); // ne sert qu'a la lisibilite du code
28
29
/**
30
 * Transforme une couleur vectorielle R,G,B en hexa (par exemple pour usage css)
31
 *
32
 * @param int $red
33
 *     Valeur du rouge de 0 à 255.
34
 * @param int $green
35
 *     Valeur du vert de 0 à 255.
36
 * @param int $blue
37
 *     Valeur du bleu de 0 à 255.
38
 * @return string
39
 *     Le code de la couleur en hexadécimal.
40
 */
41
function _couleur_dec_to_hex($red, $green, $blue) {
42
	$red = dechex($red);
43
	$green = dechex($green);
44
	$blue = dechex($blue);
45
46
	if (strlen($red) == 1) {
47
		$red = "0" . $red;
48
	}
49
	if (strlen($green) == 1) {
50
		$green = "0" . $green;
51
	}
52
	if (strlen($blue) == 1) {
53
		$blue = "0" . $blue;
54
	}
55
56
	return "$red$green$blue";
57
}
58
59
/**
60
 * Transforme une couleur hexa en vectorielle R,G,B
61
 *
62
 * @param string $couleur
63
 *     Code couleur en hexa (#000000 à #FFFFFF).
64
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,integer|double>.

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...
65
 *     Un tableau des 3 éléments : rouge, vert, bleu.
66
 */
67
function _couleur_hex_to_dec($couleur) {
68
	$couleur = couleur_html_to_hex($couleur);
69
	$couleur = ltrim($couleur, '#');
70
	if (strlen($couleur) === 3) {
71
		$couleur = $couleur[0] . $couleur[0] . $couleur[1] . $couleur[1] . $couleur[2] . $couleur[2];
72
	}
73
	$retour["red"] = hexdec(substr($couleur, 0, 2));
0 ignored issues
show
Coding Style Comprehensibility introduced by
$retour was never initialized. Although not strictly required by PHP, it is generally a good practice to add $retour = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
74
	$retour["green"] = hexdec(substr($couleur, 2, 2));
75
	$retour["blue"] = hexdec(substr($couleur, 4, 2));
76
77
	return $retour;
78
}
79
80
/**
81
 * Donne un statut au fichier-image intermédiaire servant au traitement d'image
82
 * selon qu'il doit être gravé (fichier .src) ou pas.
83
 *
84
 * Un appel PHP direct aux fonctions de filtre d'image produira ainsi une image
85
 * permanente (gravée) ; un appel généré par le compilateur via
86
 * `filtrer('image_xx, ...)` effacera automatiquement le fichier-image temporaire.
87
 *
88
 * @param bool|string $stat
89
 *     true, false ou le statut déjà défini si traitements enchaînés.
90
 * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be false|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...
91
 *     true si il faut supprimer le fichier temporaire ; false sinon.
92
 */
93
function statut_effacer_images_temporaires($stat) {
94
	static $statut = false; // par defaut on grave toute les images
95
	if ($stat === 'get') {
96
		return $statut;
97
	}
98
	$statut = $stat ? true : false;
99
}
100
101
102
/**
103
 * Fonctions de traitement d'image
104
 *
105
 * Uniquement pour GD2.
106
 *
107
 * @pipeline_appel image_preparer_filtre
108
 * @uses extraire_attribut()
109
 * @uses inserer_attribut()
110
 * @uses tester_url_absolue()
111
 * @uses copie_locale() Si l'image est distante
112
 * @uses taille_image()
113
 * @uses _image_ratio()
114
 * @uses reconstruire_image_intermediaire()
115
 *
116
 * @param string $img
117
 *     Chemin de l'image ou balise html `<img src=... />`.
118
 * @param string $effet
119
 *     Les nom et paramètres de l'effet à apporter sur l'image
120
 *     (par exemple : reduire-300-200).
121
 * @param bool|string $forcer_format
122
 *     Un nom d'extension spécifique demandé (par exemple : jpg, png, txt...).
123
 *     Par défaut false : GD se débrouille seule).
124
 * @param array $fonction_creation
0 ignored issues
show
Documentation introduced by
Should the type for parameter $fonction_creation not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

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. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

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

Loading history...
125
 *     Un tableau à 2 éléments :
126
 *     1) string : indique le nom du filtre de traitement demandé (par exemple : `image_reduire`) ;
127
 *     2) array : tableau reprenant la valeur de `$img` et chacun des arguments passés au filtre utilisé.
128
 * @param bool $find_in_path
129
 *     false (par défaut) indique que l'on travaille sur un fichier
130
 *     temporaire (.src) ; true, sur un fichier définitif déjà existant.
131
 * @param bool $support_svg
132
 *     false (par defaut) indique que le filtre ne sait pas traiter le cas particulier du SVG
133
 *     on lui substitue un filtre generique qui ne fait rien pour ne pas briser la chaine des filtres images
134
 *     true si le filtre appelant sait traiter les SVG
135
 * @return bool|string|array
136
 *
137
 *     - false si pas de tag `<img`,
138
 *       -   si l'extension n'existe pas,
139
 *       -   si le fichier source n'existe pas,
140
 *       -   si les dimensions de la source ne sont pas accessibles,
141
 *       -   si le fichier temporaire n'existe pas,
142
 *       -   si la fonction `_imagecreatefrom{extension}` n'existe pas ;
143
 *     - "" (chaîne vide) si le fichier source est distant et n'a pas
144
 *       réussi à être copié sur le serveur ;
145
 *     - array : tableau décrivant de l'image
146
 */
147
function _image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_creation = null, $find_in_path = false, $support_svg = false) {
148
	static $images_recalcul = array();
149
	if (strlen($img) == 0) {
150
		return false;
151
	}
152
153
	$source = trim(extraire_attribut($img, 'src'));
154
	if (strlen($source) < 1) {
155
		$source = $img;
156
		$img = "<img src='$source' />";
157
	} # gerer img src="data:....base64"
158
	elseif (preg_match('@^data:image/(jpe?g|png|gif|svg+xml);base64,(.*)$@isS', $source, $regs)) {
159
		$local = sous_repertoire(_DIR_VAR, 'image-data') . md5($regs[2]) . '.' . str_replace('jpeg', 'jpg', $regs[1]);
160
		if (!file_exists($local)) {
161
			ecrire_fichier($local, base64_decode($regs[2]));
162
		}
163
		$source = $local;
164
		$img = inserer_attribut($img, 'src', $source);
165
		# eviter les mauvaises surprises lors de conversions de format
166
		$img = inserer_attribut($img, 'width', '');
167
		$img = inserer_attribut($img, 'height', '');
168
	}
169
170
	// les protocoles web prennent au moins 3 lettres
171
	if (tester_url_absolue($source)) {
172
		include_spip('inc/distant');
173
		$fichier = _DIR_RACINE . copie_locale($source);
174
		if (!$fichier) {
175
			return "";
176
		}
177
	} else {
178
		// enlever le timestamp eventuel
179
		if (strpos($source, "?") !== false) {
180
			$source = preg_replace(',[?][0-9]+$,', '', $source);
181
		}
182
		if (strpos($source, "?") !== false
183
			and strncmp($source, _DIR_IMG, strlen(_DIR_IMG)) == 0
184
			and file_exists($f = preg_replace(',[?].*$,', '', $source))
185
		) {
186
			$source = $f;
187
		}
188
		$fichier = $source;
189
	}
190
191
	$terminaison_dest = "";
192
	if ($terminaison = _image_trouver_extension($fichier)) {
193
		$terminaison_dest = ($terminaison == 'gif') ? 'png' : $terminaison;
194
	}
195
196
	if ($forcer_format !== false
197
		// ignorer forcer_format si on a une image svg, que le filtre appelant ne supporte pas SVG, et que le forcage est un autre format image
198
		and ($terminaison_dest !== 'svg' or $support_svg or !in_array($forcer_format,['png','gif','jpg']))) {
199
		$terminaison_dest = $forcer_format;
200
	}
201
202
	if (!$terminaison_dest) {
203
		return false;
204
	}
205
206
	$nom_fichier = substr($fichier, 0, strlen($fichier) - (strlen($terminaison) + 1));
207
	$fichier_dest = $nom_fichier;
208
	if (($find_in_path and $f = find_in_path($fichier) and $fichier = $f)
0 ignored issues
show
Bug introduced by
The variable $f does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
209
		or @file_exists($f = $fichier)
210
	) {
211
		// on passe la balise img a taille image qui exraira les attributs si possible
212
		// au lieu de faire un acces disque sur le fichier
213
		list($ret["hauteur"], $ret["largeur"]) = taille_image($find_in_path ? $f : $img);
214
		$date_src = @filemtime($f);
215
	} elseif (@file_exists($f = "$fichier.src")
216
		and lire_fichier($f, $valeurs)
217
		and $valeurs = unserialize($valeurs)
218
		and isset($valeurs["hauteur_dest"])
219
		and isset($valeurs["largeur_dest"])
220
	) {
221
		$ret["hauteur"] = $valeurs["hauteur_dest"];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ret was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ret = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
222
		$ret["largeur"] = $valeurs["largeur_dest"];
223
		$date_src = $valeurs["date"];
224
	} // pas de fichier source par la
225
	else {
226
		return false;
227
	}
228
229
	// pas de taille mesurable
230
	if (!($ret["hauteur"] or $ret["largeur"])) {
0 ignored issues
show
Bug introduced by
The variable $ret does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
231
		return false;
232
	}
233
234
	// les images calculees dependent du chemin du fichier source
235
	// pour une meme image source et un meme filtre on aboutira a 2 fichiers selon si l'appel est dans le public ou dans le prive
236
	// ce n'est pas totalement optimal en terme de stockage, mais chaque image est associee a un fichier .src
237
	// qui contient la methode de reconstrucion (le filtre + les arguments d'appel) et les arguments different entre prive et public
238
	// la mise en commun du fichier image cree donc un bug et des problemes qui necessiteraient beaucoup de complexite de code
239
	// alors que ca concerne peu de site au final
240
	// la release de r23632+r23633+r23634 a provoque peu de remontee de bug attestant du peu de sites impactes
241
	$identifiant = $fichier;
242
243
	// cas general :
244
	// on a un dossier cache commun et un nom de fichier qui varie avec l'effet
245
	// cas particulier de reduire :
246
	// un cache par dimension, et le nom de fichier est conserve, suffixe par la dimension aussi
247
	$cache = "cache-gd2";
248
	if (substr($effet, 0, 7) == 'reduire') {
249
		list(, $maxWidth, $maxHeight) = explode('-', $effet);
250
		list($destWidth, $destHeight) = _image_ratio($ret['largeur'], $ret['hauteur'], $maxWidth, $maxHeight);
251
		$ret['largeur_dest'] = $destWidth;
252
		$ret['hauteur_dest'] = $destHeight;
253
		$effet = "L{$destWidth}xH$destHeight";
254
		$cache = "cache-vignettes";
255
		$fichier_dest = basename($fichier_dest);
256
		if (($ret['largeur'] <= $maxWidth) && ($ret['hauteur'] <= $maxHeight)) {
257
			// on garde la terminaison initiale car image simplement copiee
258
			// et on postfixe son nom avec un md5 du path
259
			$terminaison_dest = $terminaison;
260
			$fichier_dest .= '-' . substr(md5("$identifiant"), 0, 5);
261
		} else {
262
			$fichier_dest .= '-' . substr(md5("$identifiant-$effet"), 0, 5);
263
		}
264
		$cache = sous_repertoire(_DIR_VAR, $cache);
265
		$cache = sous_repertoire($cache, $effet);
266
		# cherche un cache existant
267
		/*foreach (array('gif','jpg','png') as $fmt)
268
			if (@file_exists($cache . $fichier_dest . '.' . $fmt)) {
269
				$terminaison_dest = $fmt;
270
			}*/
271
	} else {
272
		$fichier_dest = md5("$identifiant-$effet");
273
		$cache = sous_repertoire(_DIR_VAR, $cache);
274
		$cache = sous_repertoire($cache, substr($fichier_dest, 0, 2));
275
		$fichier_dest = substr($fichier_dest, 2);
276
	}
277
278
	$fichier_dest = $cache . $fichier_dest . "." . $terminaison_dest;
279
280
	$GLOBALS["images_calculees"][] = $fichier_dest;
281
282
	$creer = true;
283
	// si recalcul des images demande, recalculer chaque image une fois
284
	if (defined('_VAR_IMAGES') and _VAR_IMAGES and !isset($images_recalcul[$fichier_dest])) {
285
		$images_recalcul[$fichier_dest] = true;
286
	} else {
287
		if (@file_exists($f = $fichier_dest)) {
288
			if (filemtime($f) >= $date_src) {
289
				$creer = false;
290
			}
291
		} else {
292
			if (@file_exists($f = "$fichier_dest.src")
293
				and lire_fichier($f, $valeurs)
294
				and $valeurs = unserialize($valeurs)
295
				and $valeurs["date"] >= $date_src
296
			) {
297
				$creer = false;
298
			}
299
		}
300
	}
301
	if ($creer) {
302
		if (!@file_exists($fichier)) {
303
			if (!@file_exists("$fichier.src")) {
304
				spip_log("Image absente : $fichier");
305
306
				return false;
307
			}
308
			# on reconstruit l'image source absente a partir de la chaine des .src
309
			reconstruire_image_intermediaire($fichier);
0 ignored issues
show
Bug introduced by
It seems like $fichier defined by $f on line 208 can also be of type boolean; however, reconstruire_image_intermediaire() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
310
		}
311
	}
312
313
	if ($creer) {
314
		spip_log("filtre image " . ($fonction_creation ? reset($fonction_creation) : '') . "[$effet] sur $fichier",
315
			"images" . _LOG_DEBUG);
316
	}
317
318
	$term_fonction = _image_trouver_extension_pertinente($fichier);
0 ignored issues
show
Bug introduced by
It seems like $fichier defined by $f on line 208 can also be of type boolean; however, _image_trouver_extension_pertinente() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
319
	$ret["fonction_imagecreatefrom"] = "_imagecreatefrom" . $term_fonction;
320
	$ret["fichier"] = $fichier;
321
	$ret["fonction_image"] = "_image_image" . $terminaison_dest;
322
	$ret["fichier_dest"] = $fichier_dest;
323
	$ret["format_source"] = ($terminaison != 'jpeg' ? $terminaison : 'jpg');
324
	$ret["format_dest"] = $terminaison_dest;
325
	$ret["date_src"] = $date_src;
326
	$ret["creer"] = $creer;
327
	$ret["class"] = extraire_attribut($img, 'class');
328
	$ret["alt"] = extraire_attribut($img, 'alt');
329
	$ret["style"] = extraire_attribut($img, 'style');
330
	$ret["tag"] = $img;
331
	if ($fonction_creation) {
332
		$ret["reconstruction"] = $fonction_creation;
333
		# ecrire ici comment creer le fichier, car il est pas sur qu'on l'ecrira reelement 
334
		# cas de image_reduire qui finalement ne reduit pas l'image source
335
		# ca evite d'essayer de le creer au prochain hit si il n'est pas la
336
		#ecrire_fichier($ret['fichier_dest'].'.src',serialize($ret),true);
337
	}
338
339
	$ret = pipeline('image_preparer_filtre', array(
340
			'args' => array(
341
				'img' => $img,
342
				'effet' => $effet,
343
				'forcer_format' => $forcer_format,
344
				'fonction_creation' => $fonction_creation,
345
				'find_in_path' => $find_in_path,
346
			),
347
			'data' => $ret
348
		)
349
	);
350
351
	// une globale pour le debug en cas de crash memoire
352
	$GLOBALS["derniere_image_calculee"] = $ret;
353
354
	// traiter le cas particulier des SVG : si le filtre n'a pas annonce explicitement qu'il savait faire, on delegue
355
	if ($term_fonction === 'svg') {
356
		if ($creer and !$support_svg) {
357
			process_image_svg_identite($ret);
358
			$ret['creer'] = false;
359
		}
360
	}
361
	else {
362
		if (!function_exists($ret["fonction_imagecreatefrom"])) {
363
			return false;
364
		}
365
	}
366
367
	return $ret;
368
}
369
370
/**
371
 * Retourne la terminaison d’un fichier image
372
 * @param string $path
373
 * @return string
374
 */
375
function _image_trouver_extension($path) {
376
	if (preg_match(",\.(gif|jpe?g|png|svg)($|[?]),i", $path, $regs)) {
377
		$terminaison = strtolower($regs[1]);
378
		return $terminaison;
379
	}
380
	return '';
381
}
382
383
/**
384
 * Tente de trouver le véritable type d’une image,
385
 * même si une image est d’extension .jpg alors que son contenu est autre chose (gif ou png)
386
 *
387
 * @param string $path
388
 * @return string Extension, dans le format attendu par les fonctions 'gd' ('jpeg' pour les .jpg par exemple)
389
 */
390
function _image_trouver_extension_pertinente($path) {
391
	$path = supprimer_timestamp($path);
392
	$terminaison = _image_trouver_extension($path);
393
	if ($terminaison == 'jpg') {
394
		$terminaison = 'jpeg';
395
	}
396
397
	if (!file_exists($path)) {
398
		return $terminaison;
399
	}
400
401
	if (!$info = @spip_getimagesize($path)) {
402
		return $terminaison;
403
	}
404
405
	if (isset($info['mime'])) {
406
		$mime = $info['mime'];
407
	}
408
	else {
409
		$mime = image_type_to_mime_type($info[2]);
410
	}
411
412
	switch (strtolower($mime)) {
413
		case 'image/png':
414
		case 'image/x-png':
415
			$_terminaison = 'png';
416
			break;
417
418
		case 'image/jpg':
419
		case 'image/jpeg':
420
		case 'image/pjpeg':
421
			$_terminaison = 'jpeg';
422
			break;
423
424
		case 'image/gif':
425
			$_terminaison = 'gif';
426
			break;
427
428
		case 'image/webp':
429
		case 'image/x-webp':
430
			$_terminaison = 'webp';
431
			break;
432
433
		case 'image/svg+xml':
434
			$_terminaison = 'svg';
435
			break;
436
437
		default:
438
			$_terminaison = '';
439
	}
440
	if ($_terminaison and $_terminaison !== $terminaison) {
441
		spip_log("Mauvaise extension du fichier : $path . Son type mime est : $mime", "images." . _LOG_INFO_IMPORTANTE);
442
		$terminaison = $_terminaison;
443
	}
444
	return $terminaison;
445
}
446
447
/**
448
 * Crée une image depuis un fichier ou une URL
449
 *
450
 * Utilise les fonctions spécifiques GD.
451
 *
452
 * @param string $filename
453
 *     Le path vers l'image à traiter (par exemple : IMG/distant/jpg/image.jpg
454
 *     ou local/cache-vignettes/L180xH51/image.jpg).
455
 * @return ressource
456
 *     Une ressource de type Image GD.
457
 */
458 View Code Duplication
function _imagecreatefromjpeg($filename) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
459
	$img = @imagecreatefromjpeg($filename);
460
	if (!$img) {
461
		spip_log("Erreur lecture imagecreatefromjpeg $filename", _LOG_CRITIQUE);
462
		erreur_squelette("Erreur lecture imagecreatefromjpeg $filename");
463
		$img = imagecreate(10, 10);
464
	}
465
466
	return $img;
467
}
468
469
/**
470
 * Crée une image depuis un fichier ou une URL (au format png)
471
 *
472
 * Utilise les fonctions spécifiques GD.
473
 *
474
 * @param string $filename
475
 *     Le path vers l'image à traiter (par exemple : IMG/distant/png/image.png
476
 *     ou local/cache-vignettes/L180xH51/image.png).
477
 * @return ressource
478
 *     Une ressource de type Image GD.
479
 */
480 View Code Duplication
function _imagecreatefrompng($filename) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
481
	$img = @imagecreatefrompng($filename);
482
	if (!$img) {
483
		spip_log("Erreur lecture imagecreatefrompng $filename", _LOG_CRITIQUE);
484
		erreur_squelette("Erreur lecture imagecreatefrompng $filename");
485
		$img = imagecreate(10, 10);
486
	}
487
488
	return $img;
489
}
490
491
/**
492
 * Crée une image depuis un fichier ou une URL (au format gif)
493
 *
494
 * Utilise les fonctions spécifiques GD.
495
 *
496
 * @param string $filename
497
 *     Le path vers l'image à traiter (par exemple : IMG/distant/gif/image.gif
498
 *     ou local/cache-vignettes/L180xH51/image.gif).
499
 * @return ressource
500
 *     Une ressource de type Image GD.
501
 */
502 View Code Duplication
function _imagecreatefromgif($filename) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
503
	$img = @imagecreatefromgif($filename);
504
	if (!$img) {
505
		spip_log("Erreur lecture imagecreatefromgif $filename", _LOG_CRITIQUE);
506
		erreur_squelette("Erreur lecture imagecreatefromgif $filename");
507
		$img = imagecreate(10, 10);
508
	}
509
510
	return $img;
511
}
512
513
/**
514
 * Affiche ou sauvegarde une image au format PNG
515
 *
516
 * Utilise les fonctions spécifiques GD.
517
 *
518
 * @param ressource $img
519
 *     Une ressource de type Image GD.
520
 * @param string $fichier
521
 *     Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.png).
522
 * @return bool
523
 *
524
 *     - false si l'image créée a une largeur nulle ou n'existe pas ;
525
 *     - true si une image est bien retournée.
526
 */
527 View Code Duplication
function _image_imagepng($img, $fichier) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
528
	if (!function_exists('imagepng')) {
529
		return false;
530
	}
531
	$tmp = $fichier . ".tmp";
532
	$ret = imagepng($img, $tmp);
533
	if (file_exists($tmp)) {
534
		$taille_test = getimagesize($tmp);
535
		if ($taille_test[0] < 1) {
536
			return false;
537
		}
538
539
		spip_unlink($fichier); // le fichier peut deja exister
540
		@rename($tmp, $fichier);
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...
541
542
		return $ret;
543
	}
544
545
	return false;
546
}
547
548
/**
549
 * Affiche ou sauvegarde une image au format GIF
550
 *
551
 * Utilise les fonctions spécifiques GD.
552
 *
553
 * @param ressource $img
554
 *     Une ressource de type Image GD.
555
 * @param string $fichier
556
 *     Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.gif).
557
 * @return bool
558
 *
559
 *     - false si l'image créée a une largeur nulle ou n'existe pas ;
560
 *     - true si une image est bien retournée.
561
 */
562 View Code Duplication
function _image_imagegif($img, $fichier) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
563
	if (!function_exists('imagegif')) {
564
		return false;
565
	}
566
	$tmp = $fichier . ".tmp";
567
	$ret = imagegif($img, $tmp);
568
	if (file_exists($tmp)) {
569
		$taille_test = getimagesize($tmp);
570
		if ($taille_test[0] < 1) {
571
			return false;
572
		}
573
574
		spip_unlink($fichier); // le fichier peut deja exister
575
		@rename($tmp, $fichier);
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...
576
577
		return $ret;
578
	}
579
580
	return false;
581
}
582
583
/**
584
 * Affiche ou sauvegarde une image au format JPG
585
 *
586
 * Utilise les fonctions spécifiques GD.
587
 *
588
 * @param ressource $img
589
 *     Une ressource de type Image GD.
590
 * @param string $fichier
591
 *     Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg).
592
 * @param int $qualite
593
 *     Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit
594
 *     fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la
595
 *     valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis
596
 *     mes_options.php).
597
 * @return bool
598
 *
599
 *     - false si l'image créée a une largeur nulle ou n'existe pas ;
600
 *     - true si une image est bien retournée.
601
 */
602
function _image_imagejpg($img, $fichier, $qualite = _IMG_GD_QUALITE) {
603
	if (!function_exists('imagejpeg')) {
604
		return false;
605
	}
606
	$tmp = $fichier . ".tmp";
607
608
	// Enable interlancing
609
	imageinterlace($img, true);
610
611
	$ret = imagejpeg($img, $tmp, $qualite);
612
613
	if (file_exists($tmp)) {
614
		$taille_test = getimagesize($tmp);
615
		if ($taille_test[0] < 1) {
616
			return false;
617
		}
618
619
		spip_unlink($fichier); // le fichier peut deja exister
620
		@rename($tmp, $fichier);
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...
621
622
		return $ret;
623
	}
624
625
	return false;
626
}
627
628
/**
629
 * Crée un fichier-image au format ICO
630
 *
631
 * Utilise les fonctions de la classe phpthumb_functions.
632
 *
633
 * @uses phpthumb_functions::GD2ICOstring()
634
 *
635
 * @param ressource $img
636
 *     Une ressource de type Image GD.
637
 * @param string $fichier
638
 *     Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg).
639
 * @return bool
640
 *     true si le fichier a bien été créé ; false sinon.
641
 */
642
function _image_imageico($img, $fichier) {
643
	$gd_image_array = array($img);
644
645
	return ecrire_fichier($fichier, phpthumb_functions::GD2ICOstring($gd_image_array));
646
}
647
648
649
/**
650
 * Sauvegarde une image au format SVG
651
 *
652
 * - N'UTILISE PAS GD -
653
 * C'est une fonction derogatoire pour faciliter le traitement des SVG
654
 *
655
 * @param string $img
656
 *     contenu du SVG ou chemin vers le SVG source (et c'est alors une copie)
657
 * @param string $fichier
658
 *     Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.png).
659
 * @return bool
660
 *
661
 *     - false si l'image créée a une largeur nulle ou n'existe pas ;
662
 *     - true si une image est bien retournée.
663
 */
664
function _image_imagesvg($img, $fichier) {
665
666
	$tmp = $fichier . ".tmp";
667
	if (strpos($img, "<") === false) {
668
		$img = supprimer_timestamp($img);
669
		if (!file_exists($img)) {
670
			return false;
671
		}
672
		@copy($img, $tmp);
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...
673
		if (filesize($tmp) == filesize($img)) {
674
			spip_unlink($fichier); // le fichier peut deja exister
675
			@rename($tmp, $fichier);
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...
676
			return true;
677
		}
678
		return false;
679
	}
680
681
	file_put_contents($tmp, $img);
682
	if (file_exists($tmp)) {
683
		$taille_test = spip_getimagesize($tmp);
684
		if ($taille_test[0] < 1) {
685
			return false;
686
		}
687
688
		spip_unlink($fichier); // le fichier peut deja exister
689
		@rename($tmp, $fichier);
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...
690
691
		return true;
692
	}
693
694
	return false;
695
}
696
697
698
/**
699
 * Finalise le traitement GD
700
 *
701
 * Crée un fichier_image temporaire .src ou vérifie que le fichier_image
702
 * définitif a bien été créé.
703
 *
704
 * @uses statut_effacer_images_temporaires()
705
 *
706
 * @param resource|string $img
707
 *     Une ressource de type Image GD (ou une string pour un SVG)
708
 * @param array $valeurs
709
 *     Un tableau des informations (tailles, traitement, path...) accompagnant
710
 *     l'image.
711
 * @param int $qualite
712
 *     N'est utilisé que pour les images jpg.
713
 *     Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit
714
 *     fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la
715
 *     valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis
716
 *     mes_options.php).
717
 * @return bool
718
 *     - true si le traitement GD s'est bien finalisé ;
719
 *     - false sinon.
720
 */
721
function _image_gd_output($img, $valeurs, $qualite = _IMG_GD_QUALITE) {
722
	$fonction = "_image_image" . $valeurs['format_dest'];
723
	$ret = false;
724
	#un flag pour reperer les images gravees
725
	$lock =
726
		!statut_effacer_images_temporaires('get') // si la fonction n'a pas ete activee, on grave tout
727
	or (@file_exists($valeurs['fichier_dest']) and !@file_exists($valeurs['fichier_dest'] . '.src'));
728
	if (
729
		function_exists($fonction)
730
		&& ($ret = $fonction($img, $valeurs['fichier_dest'], $qualite)) # on a reussi a creer l'image
731
		&& isset($valeurs['reconstruction']) # et on sait comment la resonctruire le cas echeant
732
		&& !$lock
733
	) {
734
		if (@file_exists($valeurs['fichier_dest'])) {
735
			// dans tous les cas mettre a jour la taille de l'image finale
736
			list($valeurs["hauteur_dest"], $valeurs["largeur_dest"]) = taille_image($valeurs['fichier_dest']);
737
			$valeurs['date'] = @filemtime($valeurs['fichier_dest']); // pour la retrouver apres disparition
738
			ecrire_fichier($valeurs['fichier_dest'] . '.src', serialize($valeurs), true);
739
		}
740
	}
741
742
	return $ret;
743
}
744
745
/**
746
 * Reconstruit une image à partir des sources de contrôle de son ancienne
747
 * construction
748
 *
749
 * @uses ramasse_miettes()
750
 *
751
 * @param string $fichier_manquant
752
 *     Chemin vers le fichier manquant
753
 **/
754
function reconstruire_image_intermediaire($fichier_manquant) {
755
	$reconstruire = array();
756
	$fichier = $fichier_manquant;
757
	while (strpos($fichier,"://")===false
758
		and !@file_exists($fichier)
759
		and lire_fichier($src = "$fichier.src", $source)
760
		and $valeurs = unserialize($source)
761
		and ($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...)
762
	) {
763
		spip_unlink($src); // si jamais on a un timeout pendant la reconstruction, elle se fera naturellement au hit suivant
764
		$reconstruire[] = $valeurs['reconstruction'];
765
	}
766
	while (count($reconstruire)) {
767
		$r = array_pop($reconstruire);
768
		$fonction = $r[0];
769
		$args = $r[1];
770
		call_user_func_array($fonction, $args);
771
	}
772
	// cette image intermediaire est commune a plusieurs series de filtre, il faut la conserver
773
	// mais l'on peut nettoyer les miettes de sa creation
774
	ramasse_miettes($fichier_manquant);
775
}
776
777
/**
778
 * Indique qu'un fichier d'image calculé est à conserver
779
 *
780
 * Permet de rendre une image définitive et de supprimer les images
781
 * intermédiaires à son calcul.
782
 *
783
 * Supprime le fichier de contrôle de l’image cible (le $fichier.src)
784
 * ce qui indique que l'image est définitive.
785
 *
786
 * Remonte ensuite la chaîne des fichiers de contrôle pour supprimer
787
 * les images temporaires (mais laisse les fichiers de contrôle permettant
788
 * de les reconstruire).
789
 *
790
 * @param string $fichier
791
 *     Chemin du fichier d'image calculé
792
 **/
793
function ramasse_miettes($fichier) {
794
	if (strpos($fichier,"://")!==false
795
		or !lire_fichier($src = "$fichier.src", $source)
796
		or !$valeurs = unserialize($source)
797
	) {
798
		return;
799
	}
800
	spip_unlink($src); # on supprime la reference a sa source pour marquer cette image comme non intermediaire
801
	while (
802
		($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...)
803
		and (substr($fichier, 0, strlen(_DIR_VAR)) == _DIR_VAR) # et est dans local
804
		and (lire_fichier($src = "$fichier.src",
805
			$source)) # le fichier a une source connue (c'est donc une image calculee intermediaire)
806
		and ($valeurs = unserialize($source))  # et valide
807
	) {
808
		# on efface le fichier
809
		spip_unlink($fichier);
810
		# mais laisse le .src qui permet de savoir comment reconstruire l'image si besoin
811
		#spip_unlink($src);
812
	}
813
}
814
815
816
/**
817
 * Clôture une série de filtres d'images
818
 *
819
 * Ce filtre est automatiquement appelé à la fin d'une série de filtres
820
 * d'images dans un squelette.
821
 *
822
 * @filtre
823
 * @uses reconstruire_image_intermediaire()
824
 *     Si l'image finale a déjà été supprimée car considérée comme temporaire
825
 *     par une autre série de filtres images débutant pareil
826
 * @uses ramasse_miettes()
827
 *     Pour déclarer l'image définitive et nettoyer les images intermédiaires.
828
 *
829
 * @pipeline_appel post_image_filtrer
830
 *
831
 * @param string $img
832
 *     Code HTML de l'image
833
 * @return string
834
 *     Code HTML de l'image
835
 **/
836
function image_graver($img) {
837
	// appeler le filtre post_image_filtrer qui permet de faire
838
	// des traitements auto a la fin d'une serie de filtres
839
	$img = pipeline('post_image_filtrer', $img);
840
841
	$fichier_ori = $fichier = extraire_attribut($img, 'src');
842 View Code Duplication
	if (($p = strpos($fichier, '?')) !== false) {
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...
843
		$fichier = substr($fichier, 0, $p);
844
	}
845
	if (strlen($fichier) < 1) {
846
		$fichier = $img;
847
	}
848
	# si jamais le fichier final n'a pas ete calcule car suppose temporaire
849
	# et qu'il ne s'agit pas d'une URL
850
	if (strpos($fichier,"://")===false and !@file_exists($fichier)) {
851
		reconstruire_image_intermediaire($fichier);
852
	}
853
	ramasse_miettes($fichier);
854
855
	// ajouter le timestamp si besoin
856
	if (strpos($fichier_ori, "?") === false) {
857
		// on utilise str_replace pour attraper le onmouseover des logo si besoin
858
		$img = str_replace($fichier_ori, timestamp($fichier_ori), $img);
0 ignored issues
show
Bug introduced by
It seems like $fichier_ori defined by $fichier = extraire_attribut($img, 'src') on line 841 can also be of type array; however, timestamp() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
859
	}
860
861
	return $img;
862
}
863
864
865
if (!function_exists("imagepalettetotruecolor")) {
866
	/**
867
	 * Transforme une image à palette indexée (256 couleurs max) en "vraies" couleurs RGB
868
	 *
869
	 * @note Pour compatibilité avec PHP < 5.5
870
	 *
871
	 * @link http://php.net/manual/fr/function.imagepalettetotruecolor.php
872
	 *
873
	 * @param ressource $img
874
	 * @return bool
875
	 *     - true si l'image est déjà en vrai RGB ou peut être transformée
876
	 *     - false si la transformation ne peut être faite.
877
	 **/
878
	function imagepalettetotruecolor(&$img) {
879
		if (!$img or !function_exists('imagecreatetruecolor')) {
880
			return false;
881
		} elseif (!imageistruecolor($img)) {
882
			$w = imagesx($img);
883
			$h = imagesy($img);
884
			$img1 = imagecreatetruecolor($w, $h);
885
			//Conserver la transparence si possible
886
			if (function_exists('ImageCopyResampled')) {
887
				if (function_exists("imageAntiAlias")) {
888
					imageAntiAlias($img1, true);
889
				}
890
				@imagealphablending($img1, false);
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...
891
				@imagesavealpha($img1, true);
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...
892
				@ImageCopyResampled($img1, $img, 0, 0, 0, 0, $w, $h, $w, $h);
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...
893
			} else {
894
				imagecopy($img1, $img, 0, 0, 0, 0, $w, $h);
895
			}
896
897
			$img = $img1;
898
		}
899
900
		return true;
901
	}
902
}
903
904
/**
905
 * Applique des attributs de taille (width, height) à une balise HTML
906
 *
907
 * Utilisé avec des balises `<img>` tout particulièrement.
908
 *
909
 * Modifie l'attribut style s'il était renseigné, en enlevant les
910
 * informations éventuelles width / height dedans.
911
 *
912
 * @uses extraire_attribut()
913
 * @uses inserer_attribut()
914
 *
915
 * @param string $tag
916
 *     Code html de la balise
917
 * @param int $width
918
 *     Hauteur
919
 * @param int $height
920
 *     Largeur
921
 * @param bool|string $style
922
 *     Attribut html style à appliquer.
923
 *     False extrait celui présent dans la balise
924
 * @return string
925
 *     Code html modifié de la balise.
926
 **/
927
function _image_tag_changer_taille($tag, $width, $height, $style = false) {
928
	if ($style === false) {
929
		$style = extraire_attribut($tag, 'style');
930
	}
931
932
	// enlever le width et height du style
933
	$style = preg_replace(",(^|;)\s*(width|height)\s*:\s*[^;]+,ims", "", $style);
934
	if ($style and $style[0] == ';') {
935
		$style = substr($style, 1);
936
	}
937
938
	// mettre des attributs de width et height sur les images, 
939
	// ca accelere le rendu du navigateur
940
	// ca permet aux navigateurs de reserver la bonne taille 
941
	// quand on a desactive l'affichage des images.
942
	$tag = inserer_attribut($tag, 'width', round($width));
943
	$tag = inserer_attribut($tag, 'height', round($height));
944
945
	// attributs deprecies. Transformer en CSS
946
	if ($espace = extraire_attribut($tag, 'hspace')) {
947
		$style = "margin:${espace}px;" . $style;
948
		$tag = inserer_attribut($tag, 'hspace', '');
949
	}
950
951
	$tag = inserer_attribut($tag, 'style', $style, true, $style ? false : true);
0 ignored issues
show
Bug introduced by
It seems like $style defined by preg_replace(',(^|;)\\s*...[^;]+,ims', '', $style) on line 933 can also be of type array<integer,string>; however, inserer_attribut() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
952
953
	return $tag;
954
}
955
956
957
/**
958
 * Écriture de la balise img en sortie de filtre image
959
 *
960
 * Reprend le tag initial et surcharge les attributs modifiés
961
 *
962
 * @pipeline_appel image_ecrire_tag_preparer
963
 * @pipeline_appel image_ecrire_tag_finir
964
 *
965
 * @uses _image_tag_changer_taille()
966
 * @uses extraire_attribut()
967
 * @uses inserer_attribut()
968
 * @see  _image_valeurs_trans()
969
 *
970
 * @param array $valeurs
971
 *     Description de l'image tel que retourné par `_image_valeurs_trans()`
972
 * @param array $surcharge
973
 *     Permet de surcharger certaines descriptions présentes dans `$valeurs`
974
 *     tel que 'style', 'width', 'height'
975
 * @return string
976
 *     Retourne le code HTML de l'image
977
 **/
978
function _image_ecrire_tag($valeurs, $surcharge = array()) {
979
	$valeurs = pipeline('image_ecrire_tag_preparer', $valeurs);
980
981
	// fermer les tags img pas bien fermes;
982
	$tag = str_replace(">", "/>", str_replace("/>", ">", $valeurs['tag']));
983
984
	// le style
985
	$style = $valeurs['style'];
986
	if (isset($surcharge['style'])) {
987
		$style = $surcharge['style'];
988
		unset($surcharge['style']);
989
	}
990
991
	// traiter specifiquement la largeur et la hauteur
992
	$width = $valeurs['largeur'];
993
	if (isset($surcharge['width'])) {
994
		$width = $surcharge['width'];
995
		unset($surcharge['width']);
996
	}
997
	$height = $valeurs['hauteur'];
998
	if (isset($surcharge['height'])) {
999
		$height = $surcharge['height'];
1000
		unset($surcharge['height']);
1001
	}
1002
1003
	$tag = _image_tag_changer_taille($tag, $width, $height, $style);
1004
	// traiter specifiquement le src qui peut etre repris dans un onmouseout
1005
	// on remplace toute les ref a src dans le tag
1006
	$src = extraire_attribut($tag, 'src');
1007
	if (isset($surcharge['src'])) {
1008
		$tag = str_replace($src, $surcharge['src'], $tag);
1009
		// si il y a des & dans src, alors ils peuvent provenir d'un &amp
1010
		// pas garanti comme methode, mais mieux que rien
1011
		if (strpos($src, '&') !== false) {
1012
			$tag = str_replace(str_replace("&", "&amp;", $src), $surcharge['src'], $tag);
1013
		}
1014
		$src = $surcharge['src'];
0 ignored issues
show
Unused Code introduced by
$src is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1015
		unset($surcharge['src']);
1016
	}
1017
1018
	$class = $valeurs['class'];
1019
	if (isset($surcharge['class'])) {
1020
		$class = $surcharge['class'];
1021
		unset($surcharge['class']);
1022
	}
1023
	if (strlen($class)) {
1024
		$tag = inserer_attribut($tag, 'class', $class);
1025
	}
1026
1027
	if (count($surcharge)) {
1028
		foreach ($surcharge as $attribut => $valeur) {
1029
			$tag = inserer_attribut($tag, $attribut, $valeur);
1030
		}
1031
	}
1032
1033
	$tag = pipeline('image_ecrire_tag_finir',
1034
		array(
1035
			'args' => array(
1036
				'valeurs' => $valeurs,
1037
				'surcharge' => $surcharge,
1038
			),
1039
			'data' => $tag
1040
		)
1041
	);
1042
1043
	return $tag;
1044
}
1045
1046
/**
1047
 * Crée si possible une miniature d'une image
1048
 *
1049
 * @see  _image_valeurs_trans()
1050
 * @uses _image_ratio()
1051
 *
1052
 * @param array $valeurs
1053
 *     Description de l'image, telle que retournée par `_image_valeurs_trans()`
1054
 * @param int $maxWidth
1055
 *     Largeur maximum en px de la miniature à réaliser
1056
 * @param int $maxHeight
1057
 *     Hauteur maximum en px de la miniateure à réaliser
1058
 * @param string $process
1059
 *     Librairie graphique à utiliser (gd1, gd2, netpbm, convert, imagick).
1060
 *     AUTO utilise la librairie sélectionnée dans la configuration.
1061
 * @param bool $force
1062
 * @return array|null
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string|array?

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...
1063
 *     Description de l'image, sinon null.
1064
 **/
1065
function _image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process = 'AUTO', $force = false) {
1066
	// ordre de preference des formats graphiques pour creer les vignettes
1067
	// le premier format disponible, selon la methode demandee, est utilise
1068
	$image = $valeurs['fichier'];
1069
	$format = $valeurs['format_source'];
1070
	$destdir = dirname($valeurs['fichier_dest']);
1071
	$destfile = basename($valeurs['fichier_dest'], "." . $valeurs["format_dest"]);
1072
1073
	$format_sortie = $valeurs['format_dest'];
1074
1075 View Code Duplication
	if (($process == 'AUTO') and isset($GLOBALS['meta']['image_process'])) {
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...
1076
		$process = $GLOBALS['meta']['image_process'];
1077
	}
1078
1079
	// si le doc n'est pas une image, refuser
1080
	if (!$force and !in_array($format, formats_image_acceptables())) {
1081
		return;
1082
	}
1083
	$destination = "$destdir/$destfile";
1084
1085
	// calculer la taille
1086
	if (($srcWidth = $valeurs['largeur']) && ($srcHeight = $valeurs['hauteur'])) {
1087
		if (!($destWidth = $valeurs['largeur_dest']) || !($destHeight = $valeurs['hauteur_dest'])) {
1088
			list($destWidth, $destHeight) = _image_ratio($valeurs['largeur'], $valeurs['hauteur'], $maxWidth, $maxHeight);
1089
		}
1090
	} elseif ($process == 'convert' or $process == 'imagick') {
1091
		$destWidth = $maxWidth;
1092
		$destHeight = $maxHeight;
1093
	} else {
1094
		spip_log("echec $process sur $image");
1095
1096
		return;
1097
	}
1098
1099
	$vignette = '';
1100
1101
	// Si l'image est de la taille demandee (ou plus petite), simplement la retourner
1102
	if ($srcWidth and $srcWidth <= $maxWidth and $srcHeight <= $maxHeight) {
1103
		$vignette = $destination . '.' . $format;
1104
		@copy($image, $vignette);
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...
1105
	}
1106
1107
	elseif ($valeurs["format_source"] === 'svg') {
1108
		if ($svg = svg_redimensionner($valeurs['fichier'], $destWidth, $destHeight)){
1109
			$format_sortie = 'svg';
1110
			$vignette = $destination . "." . $format_sortie;
1111
			$valeurs['fichier_dest'] = $vignette;
1112
			_image_gd_output($svg, $valeurs);
0 ignored issues
show
Bug introduced by
It seems like $svg defined by svg_redimensionner($vale...destWidth, $destHeight) on line 1108 can also be of type boolean; however, _image_gd_output() does only seem to accept resource|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1113
		}
1114
	}
1115
1116
	// imagemagick en ligne de commande
1117
	elseif ($process == 'convert') {
1118
		if (!defined('_CONVERT_COMMAND')) {
1119
			define('_CONVERT_COMMAND', 'convert');
1120
		} // Securite : mes_options.php peut preciser le chemin absolu
1121
		if (!defined('_RESIZE_COMMAND')) {
1122
			define('_RESIZE_COMMAND', _CONVERT_COMMAND . ' -quality ' . _IMG_CONVERT_QUALITE . ' -resize %xx%y! %src %dest');
1123
		}
1124
		$vignette = $destination . "." . $format_sortie;
1125
		$commande = str_replace(
1126
			array('%x', '%y', '%src', '%dest'),
1127
			array(
1128
				$destWidth,
1129
				$destHeight,
1130
				escapeshellcmd($image),
1131
				escapeshellcmd($vignette)
1132
			),
1133
			_RESIZE_COMMAND);
1134
		spip_log($commande);
1135
		exec($commande);
1136
		if (!@file_exists($vignette)) {
1137
			spip_log("echec convert sur $vignette");
1138
1139
			return;  // echec commande
1140
		}
1141
	}
1142
1143
	// php5 imagemagick
1144
	elseif ($process == 'imagick') {
1145
		$vignette = "$destination." . $format_sortie;
1146
1147
		if (!class_exists('Imagick')) {
1148
			spip_log("Classe Imagick absente !", _LOG_ERREUR);
1149
1150
			return;
1151
		}
1152
		$imagick = new Imagick();
1153
		$imagick->readImage($image);
1154
		$imagick->resizeImage($destWidth, $destHeight, Imagick::FILTER_LANCZOS,
1155
			1);//, IMAGICK_FILTER_LANCZOS, _IMG_IMAGICK_QUALITE / 100);
1156
		$imagick->writeImage($vignette);
1157
1158
		if (!@file_exists($vignette)) {
1159
			spip_log("echec imagick sur $vignette");
1160
1161
			return;
1162
		}
1163
	}
1164
1165
	// netpbm
1166
	elseif ($process == "netpbm") {
1167
		if (!defined('_PNMSCALE_COMMAND')) {
1168
			define('_PNMSCALE_COMMAND', 'pnmscale');
1169
		} // Securite : mes_options.php peut preciser le chemin absolu
1170
		if (_PNMSCALE_COMMAND == '') {
1171
			return;
1172
		}
1173
		$vignette = $destination . "." . $format_sortie;
1174
		$pnmtojpeg_command = str_replace("pnmscale", "pnmtojpeg", _PNMSCALE_COMMAND);
1175
		if ($format == "jpg") {
1176
1177
			$jpegtopnm_command = str_replace("pnmscale", "jpegtopnm", _PNMSCALE_COMMAND);
1178
			exec("$jpegtopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette");
1179
			if (!($s = @filesize($vignette))) {
1180
				spip_unlink($vignette);
1181
			}
1182
			if (!@file_exists($vignette)) {
1183
				spip_log("echec netpbm-jpg sur $vignette");
1184
1185
				return;
1186
			}
1187
		} else {
1188
			if ($format == "gif") {
1189
				$giftopnm_command = str_replace("pnmscale", "giftopnm", _PNMSCALE_COMMAND);
1190
				exec("$giftopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette");
1191
				if (!($s = @filesize($vignette))) {
1192
					spip_unlink($vignette);
1193
				}
1194
				if (!@file_exists($vignette)) {
1195
					spip_log("echec netpbm-gif sur $vignette");
1196
1197
					return;
1198
				}
1199
			} else {
1200
				if ($format == "png") {
1201
					$pngtopnm_command = str_replace("pnmscale", "pngtopnm", _PNMSCALE_COMMAND);
1202
					exec("$pngtopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette");
1203
					if (!($s = @filesize($vignette))) {
1204
						spip_unlink($vignette);
1205
					}
1206
					if (!@file_exists($vignette)) {
1207
						spip_log("echec netpbm-png sur $vignette");
1208
1209
						return;
1210
					}
1211
				}
1212
			}
1213
		}
1214
	}
1215
1216
	// gd ou gd2
1217
	elseif ($process == 'gd1' or $process == 'gd2') {
1218
		if (!function_exists('gd_info')) {
1219
			spip_log("Librairie GD absente !", _LOG_ERREUR);
1220
1221
			return;
1222
		}
1223
		if (_IMG_GD_MAX_PIXELS && $srcWidth * $srcHeight > _IMG_GD_MAX_PIXELS) {
1224
			spip_log("vignette gd1/gd2 impossible : " . $srcWidth * $srcHeight . "pixels");
0 ignored issues
show
Bug introduced by
The variable $srcHeight does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1225
1226
			return;
1227
		}
1228
		$destFormat = $format_sortie;
1229
		if (!$destFormat) {
1230
			spip_log("pas de format pour $image");
1231
1232
			return;
1233
		}
1234
1235
		$fonction_imagecreatefrom = $valeurs['fonction_imagecreatefrom'];
1236
		if (!function_exists($fonction_imagecreatefrom)) {
1237
			return '';
1238
		}
1239
		$srcImage = @$fonction_imagecreatefrom($image);
1240
		if (!$srcImage) {
1241
			spip_log("echec gd1/gd2");
1242
1243
			return;
1244
		}
1245
1246
		// Initialisation de l'image destination
1247
		$destImage = null;
1248
		if ($process == 'gd2' and $destFormat != "gif") {
1249
			$destImage = ImageCreateTrueColor($destWidth, $destHeight);
1250
		}
1251
		if (!$destImage) {
1252
			$destImage = ImageCreate($destWidth, $destHeight);
1253
		}
1254
1255
		// Recopie de l'image d'origine avec adaptation de la taille 
1256
		$ok = false;
1257
		if (($process == 'gd2') and function_exists('ImageCopyResampled')) {
1258
			if ($format == "gif") {
1259
				// Si un GIF est transparent, 
1260
				// fabriquer un PNG transparent  
1261
				$transp = imagecolortransparent($srcImage);
1262
				if ($transp > 0) {
1263
					$destFormat = "png";
1264
				}
1265
			}
1266
			if ($destFormat == "png") {
1267
				// Conserver la transparence 
1268
				if (function_exists("imageAntiAlias")) {
1269
					imageAntiAlias($destImage, true);
1270
				}
1271
				@imagealphablending($destImage, false);
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...
1272
				@imagesavealpha($destImage, true);
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...
1273
			}
1274
			$ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
1275
		}
1276
		if (!$ok) {
1277
			$ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
0 ignored issues
show
Unused Code introduced by
$ok is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1278
		}
1279
1280
		// Sauvegarde de l'image destination
1281
		$valeurs['fichier_dest'] = $vignette = "$destination.$destFormat";
1282
		$valeurs['format_dest'] = $format = $destFormat;
1283
		_image_gd_output($destImage, $valeurs);
1284
1285
		if ($srcImage) {
1286
			ImageDestroy($srcImage);
1287
		}
1288
		ImageDestroy($destImage);
1289
	}
1290
1291
	if (!$vignette or !$size = @spip_getimagesize($vignette)) {
1292
		$size = array($destWidth, $destHeight);
1293
	}
1294
1295
	// Gaffe: en safe mode, pas d'acces a la vignette,
1296
	// donc risque de balancer "width='0'", ce qui masque l'image sous MSIE
1297
	if ($size[0] < 1) {
1298
		$size[0] = $destWidth;
1299
	}
1300
	if ($size[1] < 1) {
1301
		$size[1] = $destHeight;
1302
	}
1303
1304
	$retour['width'] = $largeur = $size[0];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$retour was never initialized. Although not strictly required by PHP, it is generally a good practice to add $retour = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
Unused Code introduced by
$largeur is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1305
	$retour['height'] = $hauteur = $size[1];
0 ignored issues
show
Unused Code introduced by
$hauteur is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1306
1307
	$retour['fichier'] = $vignette;
1308
	$retour['format'] = $format;
1309
	$retour['date'] = @filemtime($vignette);
1310
1311
	// renvoyer l'image
1312
	return $retour;
1313
}
1314
1315
/**
1316
 * Réduire des dimensions en respectant un ratio
1317
 *
1318
 * Réduit des dimensions (hauteur, largeur) pour qu'elles
1319
 * soient incluses dans une hauteur et largeur maximum fournies
1320
 * en respectant la proportion d'origine
1321
 *
1322
 * @example `image_ratio(1000, 1000, 100, 10)` donne `array(10, 10, 100)`
1323
 * @see ratio_passe_partout() Assez proche.
1324
 *
1325
 * @param int $srcWidth Largeur de l'image source
1326
 * @param int $srcHeight Hauteur de l'image source
1327
 * @param int $maxWidth Largeur maximum souhaitée
1328
 * @param int $maxHeight Hauteur maximum souhaitée
1329
 * @return array Liste [ largeur, hauteur, ratio de réduction ]
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<double|integer>.

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...
1330
 **/
1331 View Code Duplication
function _image_ratio($srcWidth, $srcHeight, $maxWidth, $maxHeight) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1332
	$ratioWidth = $srcWidth / $maxWidth;
1333
	$ratioHeight = $srcHeight / $maxHeight;
1334
1335
	if ($ratioWidth <= 1 and $ratioHeight <= 1) {
1336
		$destWidth = $srcWidth;
1337
		$destHeight = $srcHeight;
1338
	} elseif ($ratioWidth < $ratioHeight) {
1339
		$destWidth = $srcWidth / $ratioHeight;
1340
		$destHeight = $maxHeight;
1341
	} else {
1342
		$destWidth = $maxWidth;
1343
		$destHeight = $srcHeight / $ratioWidth;
1344
	}
1345
1346
	return array(
1347
		ceil($destWidth),
1348
		ceil($destHeight),
1349
		max($ratioWidth, $ratioHeight)
1350
	);
1351
}
1352
1353
/**
1354
 * Réduire des dimensions en respectant un ratio sur la plus petite dimension
1355
 *
1356
 * Réduit des dimensions (hauteur, largeur) pour qu'elles
1357
 * soient incluses dans la plus grande hauteur ou largeur maximum fournie
1358
 * en respectant la proportion d'origine
1359
 *
1360
 * @example `ratio_passe_partout(1000, 1000, 100, 10)` donne `array(100, 100, 10)`
1361
 * @see _image_ratio() Assez proche.
1362
 *
1363
 * @param int $srcWidth Largeur de l'image source
1364
 * @param int $srcHeight Hauteur de l'image source
1365
 * @param int $maxWidth Largeur maximum souhaitée
1366
 * @param int $maxHeight Hauteur maximum souhaitée
1367
 * @return array Liste [ largeur, hauteur, ratio de réduction ]
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<double|integer>.

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...
1368
 **/
1369 View Code Duplication
function ratio_passe_partout($srcWidth, $srcHeight, $maxWidth, $maxHeight) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1370
	$ratioWidth = $srcWidth / $maxWidth;
1371
	$ratioHeight = $srcHeight / $maxHeight;
1372
1373
	if ($ratioWidth <= 1 and $ratioHeight <= 1) {
1374
		$destWidth = $srcWidth;
1375
		$destHeight = $srcHeight;
1376
	} elseif ($ratioWidth > $ratioHeight) {
1377
		$destWidth = $srcWidth / $ratioHeight;
1378
		$destHeight = $maxHeight;
1379
	} else {
1380
		$destWidth = $maxWidth;
1381
		$destHeight = $srcHeight / $ratioWidth;
1382
	}
1383
1384
	return array(
1385
		ceil($destWidth),
1386
		ceil($destHeight),
1387
		min($ratioWidth, $ratioHeight)
1388
	);
1389
}
1390
1391
1392
/**
1393
 * Fonction identite de traitement par defaut des images SVG
1394
 * (quand un filtre n'annonce pas qu'il sait traiter un SVG on applique cette fonction a la place)
1395
 *
1396
 * @param array $image
1397
 *   tableau des valeurs crees par _image_valeurs_trans
1398
 * @return string
1399
 */
1400
function process_image_svg_identite($image) {
1401
	if ($image['creer']) {
1402
		$source = $image['fichier'];
1403
		_image_gd_output($source, $image);
1404
	}
1405
1406
	return _image_ecrire_tag($image, array('src' => $image['fichier_dest']));
1407
}
1408
1409
1410
/**
1411
 * Réduit une image
1412
 *
1413
 * @uses extraire_attribut()
1414
 * @uses inserer_attribut()
1415
 * @uses _image_valeurs_trans()
1416
 * @uses _image_ratio()
1417
 * @uses _image_tag_changer_taille()
1418
 * @uses _image_ecrire_tag()
1419
 * @uses _image_creer_vignette()
1420
 *
1421
 * @param array $fonction
1422
 *     Un tableau à 2 éléments :
1423
 *     1) string : indique le nom du filtre de traitement demandé (par exemple : `image_reduire`) ;
1424
 *     2) array : tableau reprenant la valeur de `$img` et chacun des arguments passés au filtre utilisé.
1425
 * @param string $img
1426
 *     Chemin de l'image ou texte contenant une balise img
1427
 * @param int $taille
1428
 *     Largeur désirée
1429
 * @param int $taille_y
1430
 *     Hauteur désirée
1431
 * @param bool $force
1432
 * @param string $process
1433
 *     Librairie graphique à utiliser (gd1, gd2, netpbm, convert, imagick).
1434
 *     AUTO utilise la librairie sélectionnée dans la configuration.
1435
 * @return string
1436
 *     Code HTML de la balise img produite
1437
 **/
1438
function process_image_reduire($fonction, $img, $taille, $taille_y, $force, $process = 'AUTO') {
1439
	$image = false;
1440 View Code Duplication
	if (($process == 'AUTO') and isset($GLOBALS['meta']['image_process'])) {
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...
1441
		$process = $GLOBALS['meta']['image_process'];
1442
	}
1443
	# determiner le format de sortie
1444
	$format_sortie = false; // le choix par defaut sera bon
1445
	if ($process == "netpbm") {
1446
		$format_sortie = "jpg";
1447
	} elseif ($process == 'gd1' or $process == 'gd2') {
1448
		$image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}", $format_sortie, $fonction, false, _SVG_SUPPORTED);
1449
1450
		// on verifie que l'extension choisie est bonne (en principe oui)
1451
		$gd_formats = formats_image_acceptables(true);
1452
		if (is_array($image)
1453
			and (!in_array($image['format_dest'], $gd_formats)
1454
				or ($image['format_dest'] == 'gif' and !function_exists('ImageGif'))
1455
			)
1456
		) {
1457
			if ($image['format_source'] == 'jpg') {
1458
				$formats_sortie = array('jpg', 'png', 'gif');
1459
			} else // les gif sont passes en png preferentiellement pour etre homogene aux autres filtres images
1460
			{
1461
				$formats_sortie = array('png', 'jpg', 'gif');
1462
			}
1463
			// Choisir le format destination
1464
			// - on sauve de preference en JPEG (meilleure compression)
1465
			// - pour le GIF : les GD recentes peuvent le lire mais pas l'ecrire
1466
			# bug : gd_formats contient la liste des fichiers qu'on sait *lire*,
1467
			# pas *ecrire*
1468
			$format_sortie = "";
1469
			foreach ($formats_sortie as $fmt) {
1470
				if (in_array($fmt, $gd_formats)) {
1471
					if ($fmt <> "gif" or function_exists('ImageGif')) {
1472
						$format_sortie = $fmt;
1473
					}
1474
					break;
1475
				}
1476
			}
1477
			$image = false;
1478
		}
1479
	}
1480
1481
	if (!is_array($image)) {
1482
		$image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}", $format_sortie, $fonction, false, _SVG_SUPPORTED);
1483
	}
1484
1485
	if (!is_array($image) or !$image['largeur'] or !$image['hauteur']) {
1486
		spip_log("image_reduire_src:pas de version locale de $img");
1487
		// on peut resizer en mode html si on dispose des elements
1488
		if ($srcw = extraire_attribut($img, 'width')
1489
			and $srch = extraire_attribut($img, 'height')
1490
		) {
1491
			list($w, $h) = _image_ratio($srcw, $srch, $taille, $taille_y);
1492
1493
			return _image_tag_changer_taille($img, $w, $h);
1494
		}
1495
		// la on n'a pas d'infos sur l'image source... on refile le truc a css
1496
		// sous la forme style='max-width: NNpx;'
1497
		return inserer_attribut($img, 'style',
1498
			"max-width: ${taille}px; max-height: ${taille_y}px");
1499
	}
1500
1501
	// si l'image est plus petite que la cible retourner une copie cachee de l'image
1502
	if (($image['largeur'] <= $taille) && ($image['hauteur'] <= $taille_y)) {
1503
		if ($image['creer']) {
1504
			@copy($image['fichier'], $image['fichier_dest']);
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...
1505
		}
1506
1507
		return _image_ecrire_tag($image, array('src' => $image['fichier_dest']));
1508
	}
1509
1510
	if ($image['creer'] == false && !$force) {
1511
		return _image_ecrire_tag($image,
1512
			array('src' => $image['fichier_dest'], 'width' => $image['largeur_dest'], 'height' => $image['hauteur_dest']));
1513
	}
1514
1515
	if (in_array($image["format_source"], formats_image_acceptables())) {
1516
		$destWidth = $image['largeur_dest'];
1517
		$destHeight = $image['hauteur_dest'];
1518
		$logo = $image['fichier'];
1519
		$date = $image["date_src"];
1520
		$preview = _image_creer_vignette($image, $taille, $taille_y, $process, $force);
1521
1522
		if ($preview && $preview['fichier']) {
1523
			$logo = $preview['fichier'];
1524
			$destWidth = $preview['width'];
1525
			$destHeight = $preview['height'];
1526
			$date = $preview['date'];
1527
		}
1528
		// dans l'espace prive mettre un timestamp sur l'adresse 
1529
		// de l'image, de facon a tromper le cache du navigateur
1530
		// quand on fait supprimer/reuploader un logo
1531
		// (pas de filemtime si SAFE MODE)
1532
		$date = test_espace_prive() ? ('?' . $date) : '';
1533
1534
		return _image_ecrire_tag($image, array('src' => "$logo$date", 'width' => $destWidth, 'height' => $destHeight));
1535
	}
1536
	else {
1537
		# BMP, tiff ... les redacteurs osent tout!
1538
		return $img;
1539
	}
1540
}
1541
1542
/**
1543
 * Produire des fichiers au format .ico
1544
 *
1545
 * Avec du code récupéré de phpThumb()
1546
 *
1547
 * @author James Heinrich <[email protected]>
1548
 * @link http://phpthumb.sourceforge.net
1549
 *
1550
 * Class phpthumb_functions
1551
 */
1552
class phpthumb_functions {
1553
1554
	/**
1555
	 * Retourne la couleur d'un pixel dans une image
1556
	 *
1557
	 * @param ressource $img
1558
	 * @param int $x
1559
	 * @param int $y
1560
	 * @return array|bool
1561
	 */
1562
	public static function GetPixelColor(&$img, $x, $y) {
1563
		if (!is_resource($img)) {
1564
			return false;
1565
		}
1566
1567
		return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
1568
	}
1569
1570
	/**
1571
	 * Retourne un nombre dans une représentation en Little Endian
1572
	 *
1573
	 * @param int $number
1574
	 * @param int $minbytes
1575
	 * @return string
1576
	 */
1577
	public static function LittleEndian2String($number, $minbytes = 1) {
1578
		$intstring = '';
1579
		while ($number > 0) {
1580
			$intstring = $intstring . chr($number & 255);
1581
			$number >>= 8;
1582
		}
1583
1584
		return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
1585
	}
1586
1587
	/**
1588
	 * Transforme une ressource GD en image au format ICO
1589
	 *
1590
	 * @param array $gd_image_array
1591
	 *     Tableau de ressources d'images GD
1592
	 * @return string
1593
	 *     Image au format ICO
1594
	 */
1595
	public static function GD2ICOstring(&$gd_image_array) {
1596
		foreach ($gd_image_array as $key => $gd_image) {
1597
1598
			$ImageWidths[$key] = ImageSX($gd_image);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ImageWidths was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ImageWidths = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1599
			$ImageHeights[$key] = ImageSY($gd_image);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ImageHeights was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ImageHeights = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1600
			$bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$bpp was never initialized. Although not strictly required by PHP, it is generally a good practice to add $bpp = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1601
			$totalcolors[$key] = ImageColorsTotal($gd_image);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$totalcolors was never initialized. Although not strictly required by PHP, it is generally a good practice to add $totalcolors = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1602
1603
			$icXOR[$key] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$icXOR was never initialized. Although not strictly required by PHP, it is generally a good practice to add $icXOR = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1604
			for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) {
0 ignored issues
show
Bug introduced by
The variable $ImageHeights does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1605
				for ($x = 0; $x < $ImageWidths[$key]; $x++) {
0 ignored issues
show
Bug introduced by
The variable $ImageWidths does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1606
					$argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y);
1607
					$a = round(255 * ((127 - $argb['alpha']) / 127));
1608
					$r = $argb['red'];
1609
					$g = $argb['green'];
1610
					$b = $argb['blue'];
1611
1612
					if ($bpp[$key] == 32) {
1613
						$icXOR[$key] .= chr($b) . chr($g) . chr($r) . chr($a);
0 ignored issues
show
Bug introduced by
The variable $icXOR does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1614
					} elseif ($bpp[$key] == 24) {
0 ignored issues
show
Bug introduced by
The variable $bpp does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1615
						$icXOR[$key] .= chr($b) . chr($g) . chr($r);
1616
					}
1617
1618
					if ($a < 128) {
1619
						@$icANDmask[$key][$y] .= '1';
0 ignored issues
show
Bug introduced by
The variable $icANDmask does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
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...
1620
					} else {
1621
						@$icANDmask[$key][$y] .= '0';
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...
1622
					}
1623
				}
1624
				// mask bits are 32-bit aligned per scanline
1625
				while (strlen($icANDmask[$key][$y]) % 32) {
1626
					$icANDmask[$key][$y] .= '0';
1627
				}
1628
			}
1629
			$icAND[$key] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$icAND was never initialized. Although not strictly required by PHP, it is generally a good practice to add $icAND = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1630
			foreach ($icANDmask[$key] as $y => $scanlinemaskbits) {
1631
				for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) {
1632
					$icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT)));
0 ignored issues
show
Bug introduced by
The variable $icAND does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1633
				}
1634
			}
1635
1636
		}
1637
1638
		foreach ($gd_image_array as $key => $gd_image) {
1639
			$biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8);
1640
1641
			// BITMAPINFOHEADER - 40 bytes
1642
			$BitmapInfoHeader[$key] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$BitmapInfoHeader was never initialized. Although not strictly required by PHP, it is generally a good practice to add $BitmapInfoHeader = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1643
			$BitmapInfoHeader[$key] .= "\x28\x00\x00\x00";                // DWORD  biSize;
1644
			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4);    // LONG   biWidth;
1645
			// The biHeight member specifies the combined
1646
			// height of the XOR and AND masks.
1647
			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG   biHeight;
1648
			$BitmapInfoHeader[$key] .= "\x01\x00";                    // WORD   biPlanes;
1649
			$BitmapInfoHeader[$key] .= chr($bpp[$key]) . "\x00";              // wBitCount;
1650
			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                // DWORD  biCompression;
1651
			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4);      // DWORD  biSizeImage;
1652
			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                // LONG   biXPelsPerMeter;
1653
			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                // LONG   biYPelsPerMeter;
1654
			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                // DWORD  biClrUsed;
1655
			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                // DWORD  biClrImportant;
1656
		}
1657
1658
1659
		$icondata = "\x00\x00";                    // idReserved;   // Reserved (must be 0)
1660
		$icondata .= "\x01\x00";                    // idType;	   // Resource Type (1 for icons)
1661
		$icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2);  // idCount;	  // How many images?
1662
1663
		$dwImageOffset = 6 + (count($gd_image_array) * 16);
1664
		foreach ($gd_image_array as $key => $gd_image) {
1665
			// ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
1666
1667
			$icondata .= chr($ImageWidths[$key]);           // bWidth;		  // Width, in pixels, of the image
1668
			$icondata .= chr($ImageHeights[$key]);          // bHeight;		 // Height, in pixels, of the image
1669
			$icondata .= chr($totalcolors[$key]);           // bColorCount;	 // Number of colors in image (0 if >=8bpp)
0 ignored issues
show
Bug introduced by
The variable $totalcolors does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1670
			$icondata .= "\x00";                    // bReserved;	   // Reserved ( must be 0)
1671
1672
			$icondata .= "\x01\x00";                  // wPlanes;		 // Color Planes
1673
			$icondata .= chr($bpp[$key]) . "\x00";            // wBitCount;	   // Bits per pixel
1674
1675
			$dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]);
1676
			$icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes,
1677
				4);     // dwBytesInRes;	// How many bytes in this resource?
1678
1679
			$icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset,
1680
				4);    // dwImageOffset;   // Where in the file is this image?
1681
			$dwImageOffset += strlen($BitmapInfoHeader[$key]);
0 ignored issues
show
Bug introduced by
The variable $BitmapInfoHeader does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1682
			$dwImageOffset += strlen($icXOR[$key]);
1683
			$dwImageOffset += strlen($icAND[$key]);
1684
		}
1685
1686
		foreach ($gd_image_array as $key => $gd_image) {
1687
			$icondata .= $BitmapInfoHeader[$key];
1688
			$icondata .= $icXOR[$key];
1689
			$icondata .= $icAND[$key];
1690
		}
1691
1692
		return $icondata;
1693
	}
1694
1695
}
1696