Completed
Pull Request — master (#28)
by
unknown
07:09
created

assembler.php ➔ calculer_contexte_implicite()   C

Complexity

Conditions 8
Paths 128

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 16
nc 128
nop 0
dl 0
loc 21
rs 6.3636
c 0
b 0
f 0
1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2017                                                *
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 regroupe les fonctions permettant de calculer la page et les entêtes
15
 *
16
 * Determine le contexte donne par l'URL (en tenant compte des reecritures)
17
 * grace a la fonction de passage d'URL a id (reciproque dans urls/*php)
18
 *
19
 * @package SPIP\Core\Compilateur\Assembler
20
 **/
21
22
if (!defined('_ECRIRE_INC_VERSION')) {
23
	return;
24
}
25
26
if (!defined('_CONTEXTE_IGNORE_VARIABLES')) {
27
	define('_CONTEXTE_IGNORE_VARIABLES', "/(^var_|^PHPSESSID$)/");
28
}
29
30
// http://code.spip.net/@assembler
31
function assembler($fond, $connect = '') {
32
33
	// flag_preserver est modifie ici, et utilise en globale
34
	// use_cache sert a informer le bouton d'admin pr savoir s'il met un *
35
	// contexte est utilise en globale dans le formulaire d'admin
36
37
	$GLOBALS['contexte'] = calculer_contexte();
38
	$page = array('contexte_implicite' => calculer_contexte_implicite());
39
	$page['contexte_implicite']['cache'] = $fond . preg_replace(',\.[a-zA-Z0-9]*$,', '',
40
			preg_replace('/[?].*$/', '', $GLOBALS['REQUEST_URI']));
41
	// Cette fonction est utilisee deux fois
42
	$cacher = charger_fonction('cacher', 'public', true);
43
	// Les quatre derniers parametres sont modifies par la fonction:
44
	// emplacement, validite, et, s'il est valide, contenu & age
45
	if ($cacher) {
46
		$res = $cacher($GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, $page, $lastmodified);
0 ignored issues
show
Bug introduced by
The variable $chemin_cache 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...
Bug introduced by
The variable $lastmodified seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
47
	} else {
48
		$GLOBALS['use_cache'] = -1;
49
	}
50
	// Si un resultat est retourne, c'est un message d'impossibilite
51
	if ($res) {
52
		return array('texte' => $res);
0 ignored issues
show
Bug introduced by
The variable $res 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...
53
	}
54
55
	if (!$chemin_cache || !$lastmodified) {
0 ignored issues
show
Bug introduced by
The variable $lastmodified seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
56
		$lastmodified = time();
57
	}
58
59
	$headers_only = ($_SERVER['REQUEST_METHOD'] == 'HEAD');
60
	$calculer_page = true;
61
62
	// Pour les pages non-dynamiques (indiquees par #CACHE{duree,cache-client})
63
	// une perennite valide a meme reponse qu'une requete HEAD (par defaut les
64
	// pages sont dynamiques)
65
	if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
66
		and (!defined('_VAR_MODE') or !_VAR_MODE)
67
		and $chemin_cache
68
		and isset($page['entetes'])
69
		and isset($page['entetes']['Cache-Control'])
70
		and strstr($page['entetes']['Cache-Control'], 'max-age=')
71
		and !strstr($_SERVER['SERVER_SOFTWARE'], 'IIS/')
72
	) {
73
		$since = preg_replace('/;.*/', '',
74
			$_SERVER['HTTP_IF_MODIFIED_SINCE']);
75
		$since = str_replace('GMT', '', $since);
76
		if (trim($since) == gmdate("D, d M Y H:i:s", $lastmodified)) {
0 ignored issues
show
Bug introduced by
The variable $lastmodified 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...
77
			$page['status'] = 304;
78
			$headers_only = true;
79
			$calculer_page = false;
80
		}
81
	}
82
83
	// Si requete HEAD ou Last-modified compatible, ignorer le texte
84
	// et pas de content-type (pour contrer le bouton admin de inc-public)
85
	if (!$calculer_page) {
86
		$page['texte'] = "";
87
	} else {
88
		// si la page est prise dans le cache
89
		if (!$GLOBALS['use_cache']) {
90
			// Informer les boutons d'admin du contexte
91
			// (fourni par urls_decoder_url ci-dessous lors de la mise en cache)
92
			$GLOBALS['contexte'] = $page['contexte'];
93
94
			// vider les globales url propres qui ne doivent plus etre utilisees en cas
95
			// d'inversion url => objet
96
			// plus necessaire si on utilise bien la fonction urls_decoder_url
97
			#unset($_SERVER['REDIRECT_url_propre']);
98
			#unset($_ENV['url_propre']);
99
		} else {
100
			// Compat ascendante :
101
			// 1. $contexte est global
102
			// (a evacuer car urls_decoder_url gere ce probleme ?)
103
			// et calculer la page
104
			if (!test_espace_prive()) {
105
				include_spip('inc/urls');
106
				list($fond, $GLOBALS['contexte'], $url_redirect) = urls_decoder_url(nettoyer_uri(), $fond, $GLOBALS['contexte'],
0 ignored issues
show
Unused Code introduced by
The assignment to $url_redirect is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Bug introduced by
It seems like $GLOBALS['contexte'] can also be of type integer; however, urls_decoder_url() does only seem to accept array, 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...
107
					true);
108
			}
109
			// squelette par defaut
110
			if (!strlen($fond)) {
111
				$fond = 'sommaire';
112
			}
113
114
			// produire la page : peut mettre a jour $lastmodified
115
			$produire_page = charger_fonction('produire_page', 'public');
116
			$page = $produire_page($fond, $GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, null, $page,
117
				$lastmodified, $connect);
118
			if ($page === '') {
119
				$erreur = _T('info_erreur_squelette2',
120
					array('fichier' => spip_htmlspecialchars($fond) . '.' . _EXTENSION_SQUELETTES));
121
				erreur_squelette($erreur);
122
				// eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4
123
				$page = array('texte' => '', 'erreur' => $erreur);
124
			}
125
		}
126
127
		if ($page and $chemin_cache) {
128
			$page['cache'] = $chemin_cache;
129
		}
130
131
		auto_content_type($page);
132
133
		$GLOBALS['flag_preserver'] |= headers_sent();
134
135
		// Definir les entetes si ce n'est fait 
136
		if (!$GLOBALS['flag_preserver']) {
137
			if ($GLOBALS['flag_ob']) {
138
				// Si la page est vide, produire l'erreur 404 ou message d'erreur pour les inclusions
139
				if (trim($page['texte']) === ''
140
					and _VAR_MODE != 'debug'
141
					and !isset($page['entetes']['Location']) // cette page realise une redirection, donc pas d'erreur
142
				) {
143
					$GLOBALS['contexte']['fond_erreur'] = $fond;
144
					$page = message_page_indisponible($page, $GLOBALS['contexte']);
145
				}
146
				// pas de cache client en mode 'observation'
147
				if (defined('_VAR_MODE') and _VAR_MODE) {
148
					$page['entetes']["Cache-Control"] = "no-cache,must-revalidate";
149
					$page['entetes']["Pragma"] = "no-cache";
150
				}
151
			}
152
		}
153
	}
154
155
	// Entete Last-Modified:
156
	// eviter d'etre incoherent en envoyant un lastmodified identique
157
	// a celui qu'on a refuse d'honorer plus haut (cf. #655)
158
	if ($lastmodified
159
		and !isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
160
		and !isset($page['entetes']["Last-Modified"])
161
	) {
162
		$page['entetes']["Last-Modified"] = gmdate("D, d M Y H:i:s", $lastmodified) . " GMT";
163
	}
164
165
	// fermer la connexion apres les headers si requete HEAD
166
	if ($headers_only) {
167
		$page['entetes']["Connection"] = "close";
168
	}
169
170
	return $page;
171
}
172
173
/**
174
 * Calcul le contexte de la page
175
 *
176
 * lors du calcul d'une page spip etablit le contexte a partir
177
 * des variables $_GET et $_POST, purgees des fausses variables var_*
178
 *
179
 * Note : pour hacker le contexte depuis le fichier d'appel (page.php),
180
 * il est recommande de modifier $_GET['toto'] (meme si la page est
181
 * appelee avec la methode POST).
182
 *
183
 * http://code.spip.net/@calculer_contexte
184
 *
185
 * @return array Un tableau du contexte de la page
186
 */
187
function calculer_contexte() {
188
189
	$contexte = array();
190 View Code Duplication
	foreach ($_GET as $var => $val) {
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...
191
		if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
192
			$contexte[$var] = $val;
193
		}
194
	}
195 View Code Duplication
	foreach ($_POST as $var => $val) {
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...
196
		if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
197
			$contexte[$var] = $val;
198
		}
199
	}
200
201
	return $contexte;
202
}
203
204
/**
205
 * Calculer le contexte implicite, qui n'apparait pas dans le ENV d'un cache
206
 * mais est utilise pour distinguer deux caches differents
207
 *
208
 * @staticvar string $notes
209
 * @return array
210
 */
211
function calculer_contexte_implicite() {
212
	static $notes = null;
213
	if (is_null($notes)) {
214
		$notes = charger_fonction('notes', 'inc', true);
215
	}
216
	$contexte_implicite = array(
217
		'squelettes' => $GLOBALS['dossier_squelettes'], // devrait etre 'chemin' => $GLOBALS['path_sig'], ?
218
		'host' => (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null),
219
		'https' => (isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : ''),
220
		'espace' => test_espace_prive(),
221
		'marqueur' => (isset($GLOBALS['marqueur']) ? $GLOBALS['marqueur'] : ''),
222
		'marqueur_skel' => (isset($GLOBALS['marqueur_skel']) ? $GLOBALS['marqueur_skel'] : ''),
223
		'notes' => $notes ? $notes('', 'contexter_cache') : '',
224
		'spip_version_code' => $GLOBALS['spip_version_code'],
225
	);
226
	if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
227
		$contexte_implicite['host'] .= "|" . $_SERVER['HTTP_X_FORWARDED_HOST'];
228
	}
229
230
	return $contexte_implicite;
231
}
232
233
//
234
// fonction pour compatibilite arriere, probablement superflue
235
//
236
237
// http://code.spip.net/@auto_content_type
238
function auto_content_type($page) {
239
240
	if (!isset($GLOBALS['flag_preserver'])) {
241
		$GLOBALS['flag_preserver'] = ($page && preg_match("/header\s*\(\s*.content\-type:/isx",
242
				$page['texte']) || (isset($page['entetes']['Content-Type'])));
243
	}
244
}
245
246
// http://code.spip.net/@inclure_page
247
function inclure_page($fond, $contexte, $connect = '') {
248
	static $cacher, $produire_page;
249
250
	// enlever le fond de contexte inclus car sinon il prend la main
251
	// dans les sous inclusions -> boucle infinie d'inclusion identique
252
	// (cette precaution n'est probablement plus utile)
253
	unset($contexte['fond']);
254
	$page = array('contexte_implicite' => calculer_contexte_implicite());
255
	$page['contexte_implicite']['cache'] = $fond;
256
	if (is_null($cacher)) {
257
		$cacher = charger_fonction('cacher', 'public', true);
258
	}
259
	// Les quatre derniers parametres sont modifies par la fonction:
260
	// emplacement, validite, et, s'il est valide, contenu & age
261
	if ($cacher) {
262
		$res = $cacher($contexte, $use_cache, $chemin_cache, $page, $lastinclude);
0 ignored issues
show
Bug introduced by
The variable $use_cache seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $chemin_cache 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...
Bug introduced by
The variable $lastinclude 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...
263
	} else {
264
		$use_cache = -1;
265
	}
266
	// $res = message d'erreur : on sort de la
267
	if ($res) {
268
		return array('texte' => $res);
0 ignored issues
show
Bug introduced by
The variable $res 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...
269
	}
270
271
	// Si use_cache ne vaut pas 0, la page doit etre calculee
272
	// produire la page : peut mettre a jour $lastinclude
273
	// le contexte_cache envoye a cacher() a ete conserve et est passe a produire
274
	if ($use_cache) {
275
		if (is_null($produire_page)) {
276
			$produire_page = charger_fonction('produire_page', 'public');
277
		}
278
		$page = $produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte, $page, $lastinclude, $connect);
0 ignored issues
show
Bug introduced by
The variable $use_cache 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...
279
	}
280
	// dans tous les cas, mettre a jour $GLOBALS['lastmodified']
281
	$GLOBALS['lastmodified'] = max((isset($GLOBALS['lastmodified']) ? $GLOBALS['lastmodified'] : 0), $lastinclude);
282
283
	return $page;
284
}
285
286
/**
287
 * Produire la page et la mettre en cache
288
 * lorsque c'est necessaire
289
 *
290
 * @param string $fond
291
 * @param array $contexte
292
 * @param int $use_cache
293
 * @param string $chemin_cache
294
 * @param array $contexte_cache
295
 * @param array $page
296
 * @param int $lastinclude
297
 * @param string $connect
298
 * @return array
299
 */
300
function public_produire_page_dist(
301
	$fond,
302
	$contexte,
303
	$use_cache,
304
	$chemin_cache,
305
	$contexte_cache,
306
	&$page,
307
	&$lastinclude,
308
	$connect = ''
309
) {
310
	static $parametrer, $cacher;
311
	if (!$parametrer) {
312
		$parametrer = charger_fonction('parametrer', 'public');
313
	}
314
	$page = $parametrer($fond, $contexte, $chemin_cache, $connect);
315
	// et on l'enregistre sur le disque
316
	if ($chemin_cache
317
		and $use_cache > -1
318
		and is_array($page)
319
		and count($page)
320
		and isset($page['entetes']['X-Spip-Cache'])
321
		and $page['entetes']['X-Spip-Cache'] > 0
322
	) {
323
		if (is_null($cacher)) {
324
			$cacher = charger_fonction('cacher', 'public', true);
325
		}
326
		$lastinclude = time();
327
		if ($cacher) {
328
			$cacher($contexte_cache, $use_cache, $chemin_cache, $page, $lastinclude);
329
		} else {
330
			$use_cache = -1;
0 ignored issues
show
Unused Code introduced by
$use_cache 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...
331
		}
332
	}
333
334
	return $page;
335
}
336
337
// Fonction inseree par le compilateur dans le code compile.
338
// Elle recoit un contexte pour inclure un squelette, 
339
// et les valeurs du contexte de compil prepare par memoriser_contexte_compil
340
// elle-meme appelee par calculer_balise_dynamique dans references.php:
341
// 0: sourcefile
342
// 1: codefile
343
// 2: id_boucle
344
// 3: ligne
345
// 4: langue
346
347
function inserer_balise_dynamique($contexte_exec, $contexte_compil) {
348
	if (!is_array($contexte_exec)) {
349
		echo $contexte_exec;
350
	} // message d'erreur etc
351
	else {
352
		inclure_balise_dynamique($contexte_exec, true, $contexte_compil);
353
	}
354
}
355
356
/**
357
 * Inclusion de balise dynamique
358
 * Attention, un appel explicite a cette fonction suppose certains include
359
 *
360
 * http://code.spip.net/@inclure_balise_dynamique
361
 *
362
 * @param string|array $texte
363
 * @param bool $echo Faut-il faire echo ou return
364
 * @param array $contexte_compil Contexte de la compilation
365
 * @return string
366
 */
367
function inclure_balise_dynamique($texte, $echo = true, $contexte_compil = array()) {
368
	if (is_array($texte)) {
369
370
		list($fond, $delainc, $contexte_inclus) = $texte;
371
372
		// delais a l'ancienne, c'est pratiquement mort
373
		$d = isset($GLOBALS['delais']) ? $GLOBALS['delais'] : null;
374
		$GLOBALS['delais'] = $delainc;
375
376
		$page = recuperer_fond($fond, $contexte_inclus,
377
			array('trim' => false, 'raw' => true, 'compil' => $contexte_compil));
378
379
		$texte = $page['texte'];
380
381
		$GLOBALS['delais'] = $d;
382
		// Faire remonter les entetes
383
		if (is_array($page['entetes'])) {
384
			// mais pas toutes
385
			unset($page['entetes']['X-Spip-Cache']);
386
			unset($page['entetes']['Content-Type']);
387
			if (isset($GLOBALS['page']) and is_array($GLOBALS['page'])) {
388
				if (!is_array($GLOBALS['page']['entetes'])) {
389
					$GLOBALS['page']['entetes'] = array();
390
				}
391
				$GLOBALS['page']['entetes'] =
392
					array_merge($GLOBALS['page']['entetes'], $page['entetes']);
393
			}
394
		}
395
		// _pipelines au pluriel array('nom_pipeline' => $args...) avec une syntaxe permettant plusieurs pipelines
396
		if (isset($page['contexte']['_pipelines'])
397
			and is_array($page['contexte']['_pipelines'])
398
			and count($page['contexte']['_pipelines'])
399
		) {
400
			foreach ($page['contexte']['_pipelines'] as $pipe => $args) {
401
				$args['contexte'] = $page['contexte'];
402
				unset($args['contexte']['_pipelines']); // par precaution, meme si le risque de boucle infinie est a priori nul
403
				$texte = pipeline(
404
					$pipe,
405
					array(
406
						'data' => $texte,
407
						'args' => $args
408
					),
409
					false
0 ignored issues
show
Unused Code introduced by
The call to pipeline() has too many arguments starting with false.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
410
				);
411
			}
412
		}
413
	}
414
415
	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
416
		// compatibilite : avant on donnait le numero de ligne ou rien.
417
		$ligne = intval(isset($contexte_compil[3]) ? $contexte_compil[3] : $contexte_compil);
418
		$GLOBALS['debug_objets']['resultat'][$ligne] = $texte;
419
	}
420
	if ($echo) {
421
		echo $texte;
422
	} else {
423
		return $texte;
424
	}
425
}
426
427
// http://code.spip.net/@message_page_indisponible
428
function message_page_indisponible($page, $contexte) {
429
	static $deja = false;
430
	if ($deja) {
431
		return "erreur";
432
	}
433
	$codes = array(
434
		'404' => '404 Not Found',
435
		'503' => '503 Service Unavailable',
436
	);
437
438
	$contexte['status'] = ($page !== false) ? '404' : '503';
439
	$contexte['code'] = $codes[$contexte['status']];
440
	$contexte['fond'] = '404'; // gere les 2 erreurs
441
	if (!isset($contexte['lang'])) {
442
		$contexte['lang'] = $GLOBALS['spip_lang'];
443
	}
444
445
	$deja = true;
446
	// passer aux plugins qui peuvent decider d'une page d'erreur plus pertinent
447
	// ex restriction d'acces => 401
448
	$contexte = pipeline('page_indisponible', $contexte);
449
450
	// produire la page d'erreur
451
	$page = inclure_page($contexte['fond'], $contexte);
452
	if (!$page) {
453
		$page = inclure_page('404', $contexte);
454
	}
455
	$page['status'] = $contexte['status'];
456
457
	return $page;
458
}
459
460
// temporairement ici : a mettre dans le futur inc/modeles
461
// creer_contexte_de_modele('left', 'autostart=true', ...) renvoie un array()
462
// http://code.spip.net/@creer_contexte_de_modele
463
function creer_contexte_de_modele($args) {
464
	$contexte = array();
465
	foreach ($args as $var => $val) {
466
		if (is_int($var)) { // argument pas formate
467
			if (in_array($val, array('left', 'right', 'center'))) {
468
				$var = 'align';
469
				$contexte[$var] = $val;
470
			} else {
471
				$args = explode('=', $val);
472
				if (count($args) >= 2) // Flashvars=arg1=machin&arg2=truc genere plus de deux args
473
				{
474
					$contexte[trim($args[0])] = substr($val, strlen($args[0]) + 1);
475
				} else // notation abregee
476
				{
477
					$contexte[trim($val)] = trim($val);
478
				}
479
			}
480
		} else {
481
			$contexte[$var] = $val;
482
		}
483
	}
484
485
	return $contexte;
486
}
487
488
/**
489
 * Calcule le modele et retourne la mini-page ainsi calculee
490
 *
491
 * http://code.spip.net/@inclure_modele
492
 *
493
 * @param $type string Nom du modele
494
 * @param $id int
495
 * @param $params array Paramètres du modèle
496
 * @param $lien array Informations du lien entourant l'appel du modèle en base de données
497
 * @param $connect string
498
 * @param $env array
499
 * @staticvar string $compteur
500
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|false|array? Also, consider making the array more specific, something like array<String>, or String[].

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

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
501
 */
502
function inclure_modele($type, $id, $params, $lien, $connect = '', $env = array()) {
503
504
	static $compteur;
505
	if (++$compteur > 10) {
506
		return '';
507
	} # ne pas boucler indefiniment
508
509
	$type = strtolower($type);
510
511
	$fond = $class = '';
512
513
	$params = array_filter(explode('|', $params));
514
	if ($params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $params of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
515
		list(, $soustype) = each($params);
516
		$soustype = strtolower(trim($soustype));
517
		if (in_array($soustype,
518
			array('left', 'right', 'center', 'ajax'))) {
519
			list(, $soustype) = each($params);
520
			$soustype = strtolower($soustype);
521
		}
522
523
		if (preg_match(',^[a-z0-9_]+$,', $soustype)) {
524
			if (!trouve_modele($fond = ($type . '_' . $soustype))) {
525
				$fond = '';
526
				$class = $soustype;
527
			}
528
			// enlever le sous type des params
529
			$params = array_diff($params, array($soustype));
530
		}
531
	}
532
533
	// Si ca marche pas en precisant le sous-type, prendre le type
534
	if (!$fond and !trouve_modele($fond = $type)) {
535
		spip_log("Modele $type introuvable", _LOG_INFO_IMPORTANTE);
536
537
		return false;
538
	}
539
	$fond = 'modeles/' . $fond;
540
	// Creer le contexte
541
	$contexte = $env;
542
	$contexte['dir_racine'] = _DIR_RACINE; # eviter de mixer un cache racine et un cache ecrire (meme si pour l'instant les modeles ne sont pas caches, le resultat etant different il faut que le contexte en tienne compte
543
544
	// Le numero du modele est mis dans l'environnement
545
	// d'une part sous l'identifiant "id"
546
	// et d'autre part sous l'identifiant de la cle primaire
547
	// par la fonction id_table_objet,
548
	// (<article1> =>> article =>> id_article =>> id_article=1)
549
	$_id = id_table_objet($type);
550
	$contexte['id'] = $contexte[$_id] = $id;
551
552
	if (isset($class)) {
553
		$contexte['class'] = $class;
554
	}
555
556
	// Si un lien a ete passe en parametre, ex: [<modele1>->url] ou [<modele1|title_du_lien{hreflang}->url]
557
	if ($lien) {
558
		# un eventuel guillemet (") sera reechappe par #ENV
559
		$contexte['lien'] = str_replace("&quot;", '"', $lien['href']);
560
		$contexte['lien_class'] = $lien['class'];
561
		$contexte['lien_mime'] = $lien['mime'];
562
		$contexte['lien_title'] = $lien['title'];
563
		$contexte['lien_hreflang'] = $lien['hreflang'];
564
	}
565
566
	// Traiter les parametres
567
	// par exemple : <img1|center>, <emb12|autostart=true> ou <doc1|lang=en>
568
	$arg_list = creer_contexte_de_modele($params);
569
	$contexte['args'] = $arg_list; // on passe la liste des arguments du modeles dans une variable args
570
	$contexte = array_merge($contexte, $arg_list);
571
572
	// Appliquer le modele avec le contexte
573
	$retour = recuperer_fond($fond, $contexte, array(), $connect);
574
575
	// Regarder si le modele tient compte des liens (il *doit* alors indiquer
576
	// spip_lien_ok dans les classes de son conteneur de premier niveau ;
577
	// sinon, s'il y a un lien, on l'ajoute classiquement
578
	if (strstr(' ' . ($classes = extraire_attribut($retour, 'class')) . ' ',
579
		'spip_lien_ok')) {
580
		$retour = inserer_attribut($retour, 'class',
0 ignored issues
show
Bug introduced by
It seems like $retour can also be of type array; 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...
581
			trim(str_replace(' spip_lien_ok ', ' ', " $classes ")));
582
	} else {
583
		if ($lien) {
584
			$retour = "<a href='" . $lien['href'] . "' class='" . $lien['class'] . "'>" . $retour . "</a>";
585
		}
586
	}
587
588
	$compteur--;
589
590
	return (isset($arg_list['ajax']) and $arg_list['ajax'] == 'ajax')
591
		? encoder_contexte_ajax($contexte, '', $retour)
0 ignored issues
show
Bug introduced by
It seems like $retour defined by recuperer_fond($fond, $c...xte, array(), $connect) on line 573 can also be of type array; however, encoder_contexte_ajax() does only seem to accept string|null, 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...
592
		: $retour;
593
}
594
595
// Un inclure_page qui marche aussi pour l'espace prive
596
// fonction interne a spip, ne pas appeler directement
597
// pour recuperer $page complet, utiliser:
598
// 	recuperer_fond($fond,$contexte,array('raw'=>true))
599
// http://code.spip.net/@evaluer_fond
600
function evaluer_fond($fond, $contexte = array(), $connect = null) {
601
602
	$page = inclure_page($fond, $contexte, $connect);
603
604
	if (!$page) {
605
		return $page;
606
	}
607
	// eval $page et affecte $res
608
	include _ROOT_RESTREINT . "public/evaluer_page.php";
609
610
	// Lever un drapeau (global) si le fond utilise #SESSION
611
	// a destination de public/parametrer
612
	// pour remonter vers les inclusions appelantes
613
	// il faut bien lever ce drapeau apres avoir evalue le fond
614
	// pour ne pas faire descendre le flag vers les inclusions appelees
615 View Code Duplication
	if (isset($page['invalideurs'])
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...
616
		and isset($page['invalideurs']['session'])
617
	) {
618
		$GLOBALS['cache_utilise_session'] = $page['invalideurs']['session'];
619
	}
620
621
	return $page;
622
}
623
624
625
// http://code.spip.net/@page_base_href
626
function page_base_href(&$texte) {
627
	static $set_html_base = null;
628
	if (is_null($set_html_base)) {
629
		if (!defined('_SET_HTML_BASE'))
630
			// si la profondeur est superieure a 1
631
			// est que ce n'est pas une url page ni une url action
632
			// activer par defaut
633
		{
634
			$set_html_base = ((
635
				$GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
636
				and _request(_SPIP_PAGE) !== 'login'
637
				and !_request('action')) ? true : false);
638
		} else {
639
			$set_html_base = _SET_HTML_BASE;
640
		}
641
	}
642
643
	if ($set_html_base
644
		and isset($GLOBALS['html']) and $GLOBALS['html']
645
		and $GLOBALS['profondeur_url'] > 0
646
		and ($poshead = strpos($texte, '</head>')) !== false
647
	) {
648
		$head = substr($texte, 0, $poshead);
649
		$insert = false;
0 ignored issues
show
Unused Code introduced by
$insert 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...
650
		if (strpos($head, '<base') === false) {
651
			$insert = true;
652
		} else {
653
			// si aucun <base ...> n'a de href c'est bon quand meme !
654
			$insert = true;
655
			include_spip('inc/filtres');
656
			$bases = extraire_balises($head, 'base');
657
			foreach ($bases as $base) {
658
				if (extraire_attribut($base, 'href')) {
659
					$insert = false;
660
				}
661
			}
662
		}
663
		if ($insert) {
664
			include_spip('inc/filtres_mini');
665
			// ajouter un base qui reglera tous les liens relatifs
666
			$base = url_absolue('./');
667
			$bbase = "\n<base href=\"$base\" />";
668
			if (($pos = strpos($head, '<head>')) !== false) {
669
				$head = substr_replace($head, $bbase, $pos + 6, 0);
670
			} elseif (preg_match(",<head[^>]*>,i", $head, $r)) {
671
				$head = str_replace($r[0], $r[0] . $bbase, $head);
672
			}
673
			$texte = $head . substr($texte, $poshead);
674
			// gerer les ancres
675
			$base = $_SERVER['REQUEST_URI'];
676
			// pas de guillemets ni < dans l'URL qu'on insere dans le HTML
677
			if (strpos($base,"'") or strpos($base,'"') or strpos($base,'<')) {
678
				$base = str_replace(array("'",'"','<'),array("%27",'%22','%3C'), $base);
679
			}
680 View Code Duplication
			if (strpos($texte, "href='#") !== 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...
681
				$texte = str_replace("href='#", "href='$base#", $texte);
682
			}
683 View Code Duplication
			if (strpos($texte, "href=\"#") !== 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...
684
				$texte = str_replace("href=\"#", "href=\"$base#", $texte);
685
			}
686
		}
687
	}
688
}
689
690
691
// Envoyer les entetes, en retenant ceux qui sont a usage interne
692
// et demarrent par X-Spip-...
693
// http://code.spip.net/@envoyer_entetes
694
function envoyer_entetes($entetes) {
695
	foreach ($entetes as $k => $v) #	if (strncmp($k, 'X-Spip-', 7))
696
	{
697
		@header(strlen($v) ? "$k: $v" : $k);
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...
698
	}
699
}
700