Completed
Push — spip-3.0 ( 5d8b58 )
by cam
53:01 queued 42:30
created

connect_sql.php ➔ spip_connect()   F

Complexity

Conditions 30
Paths > 20000

Size

Total Lines 94
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 30
eloc 59
c 0
b 0
f 0
nc 24064
nop 2
dl 0
loc 94
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2016                                                *
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
if (!defined('_ECRIRE_INC_VERSION')) return;
14
require_once _ROOT_RESTREINT . 'base/objets.php';
15
16
//
17
// Utilitaires indispensables autour des serveurs SQL
18
//
19
20
// API d'appel aux bases de donnees:
21
// on charge le fichier config/$serveur ($serveur='connect' pour le principal)
22
// qui est cense initaliser la connexion en appelant spip_connect_db
23
// laquelle met dans la globale db_ok la description de la connexion
24
// On la memorise dans un tableau pour permettre plusieurs serveurs.
25
// A l'installation, il faut simuler l'existence de ce fichier
26
27
// http://doc.spip.org/@spip_connect
28
function spip_connect($serveur='', $version='') {
29
	global $connexions, $spip_sql_version;
30
31
	$serveur = !is_string($serveur) ? '' : strtolower($serveur);
32
	$index = $serveur ? $serveur : 0;
33
	if (!$version) $version = $spip_sql_version;
34
	if (isset($connexions[$index][$version])) return $connexions[$index];
35
36
	include_spip('base/abstract_sql');
37
	$install = (_request('exec') == 'install');
38
39
	// Premiere connexion ?
40
	if (!($old = isset($connexions[$index]))) {
41
		$f = (!preg_match('/^[\w\.]*$/', $serveur))
42
		? '' // nom de serveur mal ecrit
43
		: ($serveur ?
44
		   ( _DIR_CONNECT. $serveur . '.php') // serveur externe
45
		    : (_FILE_CONNECT ? _FILE_CONNECT // serveur principal ok
46
		       : ($install ? _FILE_CONNECT_TMP // init du serveur principal
47
			 : ''))); // installation pas faite
48
49
		unset($GLOBALS['db_ok']);
50
		unset($GLOBALS['spip_connect_version']);
51
		if ($f) { 
52
			if (is_readable($f)) { 
53
				include($f);
54
			} elseif ($serveur AND !$install) {
55
				// chercher une declaration de serveur dans le path
56
				// qui pourra un jour servir a declarer des bases sqlite
57
				// par des plugins. Et sert aussi aux boucles POUR.
58
				find_in_path("$serveur.php",'connect/',true);
59
			}
60
		}
61
		if (!isset($GLOBALS['db_ok'])) {
62
		  // fera mieux la prochaine fois
63
			if ($install) return false;
64
			if ($f AND is_readable($f))
65
				spip_log("spip_connect: fichier de connexion '$f' OK.", _LOG_INFO_IMPORTANTE);
66
			else
67
				spip_log("spip_connect: fichier de connexion '$f' non trouve", _LOG_INFO_IMPORTANTE);
68
			spip_log("spip_connect: echec connexion ou serveur $index mal defini dans '$f'.", _LOG_HS);
69
			// ne plus reessayer si ce n'est pas l'install
70
			return $connexions[$index]=false;
71
		}
72
		$connexions[$index] = $GLOBALS['db_ok'];
73
	}
74
	// si la connexion a deja ete tentee mais a echoue, le dire!
75
	if (!$connexions[$index]) return false;
76
77
	// la connexion a reussi ou etait deja faite.
78
	// chargement de la version du jeu de fonctions
79
	// si pas dans le fichier par defaut
80
	$type = $GLOBALS['db_ok']['type'];
81
	$jeu = 'spip_' . $type .'_functions_' . $version;
82
	if (!isset($GLOBALS[$jeu])) {
83
		if (!find_in_path($type . '_' . $version . '.php', 'req/', true)){
84
		  spip_log("spip_connect: serveur $index version '$version' non defini pour '$type'", _LOG_HS);
85
			// ne plus reessayer
86
			return $connexions[$index][$version] = array();
87
		}
88
	}
89
	$connexions[$index][$version] = $GLOBALS[$jeu];
90
	if ($old) return $connexions[$index];
91
92
	$connexions[$index]['spip_connect_version'] = isset($GLOBALS['spip_connect_version']) ? $GLOBALS['spip_connect_version'] : 0;
93
94
	// initialisation de l'alphabet utilise dans les connexions SQL
95
	// si l'installation l'a determine.
96
	// Celui du serveur principal l'impose aux serveurs secondaires
97
	// s'ils le connaissent
98
99
	if (!$serveur) {
100
		$charset = spip_connect_main($GLOBALS[$jeu]);
101
		if (!$charset) {
102
			unset($connexions[$index]);
103
			spip_log("spip_connect: absence de charset", _LOG_AVERTISSEMENT);
104
			return false;
105
		}
106
	} else	{
107
		// spip_meta n'existe pas toujours dans la base
108
		// C'est le cas d'un dump sqlite par exemple 
109
		if ($connexions[$index]['spip_connect_version']
110
		AND sql_showtable('spip_meta', true, $serveur)
111
		AND $r = sql_getfetsel('valeur', 'spip_meta', "nom='charset_sql_connexion'",'','','','',$serveur))
112
			$charset = $r;
113
		else $charset = -1;
114
	}
115
	if ($charset != -1) {
116
		$f = $GLOBALS[$jeu]['set_charset'];
117
		if (function_exists($f))
118
			$f($charset, $serveur);
119
	}
120
	return $connexions[$index];
121
}
122
123
function spip_sql_erreur($serveur='')
124
{
125
	$connexion = spip_connect($serveur);
126
	$e = sql_errno($serveur);
127
	$t = (isset($connexion['type']) ? $connexion['type'] : 'sql');
128
	$m = "Erreur $e de $t: " . sql_error($serveur) . "\n" . $connexion['last'];
129
	$f = $t . $serveur;
130
	spip_log($m, $f.'.'._LOG_ERREUR);
131
}
132
133
// Cette fonction ne doit etre appelee qu'a travers la fonction sql_serveur
134
// definie dans base/abstract_sql
135
// Elle existe en tant que gestionnaire de versions,
136
// connue seulement des convertisseurs automatiques
137
138
// http://doc.spip.org/@spip_connect_sql
139
function spip_connect_sql($version, $ins='', $serveur='', $cont=false) {
140
	$desc = spip_connect($serveur, $version);
141
	if (function_exists($f = @$desc[$version][$ins])) return $f;
142
	if ($cont) return $desc;
143
	if ($ins)
144
		spip_log("Le serveur '$serveur' version $version n'a pas '$ins'", _LOG_ERREUR);
145
	include_spip('inc/minipres');
146
	echo minipres(_T('info_travaux_titre'), _T('titre_probleme_technique'));
147
	exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function spip_connect_sql() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
148
}
149
150
/**
151
 * Fonction appelee par le fichier cree dans config/ a l'instal'.
152
 * Il contient un appel direct a cette fonction avec comme arguments
153
 * les identifants de connexion.
154
 * Si la connexion reussit, la globale db_ok memorise sa description.
155
 * C'est un tableau egalement retourne en valeur, pour les appels a l'install'
156
 *
157
 * http://doc.spip.org/@spip_connect_db
158
 *
159
 * @param string $host
160
 * @param string $port
161
 * @param string $login
162
 * @param string $pass
163
 * @param string $db
164
 * @param string $type
165
 * @param string $prefixe
166
 * @param string $auth
167
 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be null|array<string,array|string>?

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

Loading history...
168
 */
169
function spip_connect_db($host, $port, $login, $pass, $db='', $type='mysql', $prefixe='', $auth='') {
170
	global $db_ok;
171
172
	// temps avant nouvelle tentative de connexion
173
	// suite a une connection echouee
174
	if (!defined('_CONNECT_RETRY_DELAY'))
175
		define('_CONNECT_RETRY_DELAY',30);
176
177
	$f = "";
178
	// un fichier de identifiant par combinaison (type,host,port,db)
179
	// pour ne pas declarer tout indisponible d'un coup
180
	// si en cours d'installation ou si db=@test@ on ne pose rien
181
	// car c'est un test de connexion
182
	if (!defined('_ECRIRE_INSTALL') AND !$db=="@test@")
183
		$f = _DIR_TMP . $type . '.' . substr(md5($host.$port.$db),0,8) . '.out';
184
	elseif ($db=='@test@')
185
		$db = '';
186
187
	if ($f
188
		AND @file_exists($f)
189
	  AND (time() - @filemtime($f) < _CONNECT_RETRY_DELAY)) {
190
		spip_log( "Echec : $f recent. Pas de tentative de connexion", _LOG_HS);
191
		return;
192
	}
193
194
	if (!$prefixe)
195
		$prefixe = isset($GLOBALS['table_prefix'])
196
		? $GLOBALS['table_prefix'] : $db;
197
	$h = charger_fonction($type, 'req', true);
198
	if (!$h) {
199
		spip_log( "les requetes $type ne sont pas fournies", _LOG_HS);
200
		return;
201
	}
202
	if ($g = $h($host, $port, $login, $pass, $db, $prefixe)) {
203
204
		if (!is_array($auth)) {
205
			// compatibilite version 0.7 initiale
206
			$g['ldap'] = $auth;
207
			$auth = array('ldap' => $auth);
208
		}
209
		$g['authentification'] = $auth;
210
		$g['type'] = $type;
211
		return $db_ok = $g;
212
	}
213
	// En cas d'indisponibilite du serveur, eviter de le bombarder
214
	if ($f) {
215
		@touch($f);
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...
216
		spip_log( "Echec connexion serveur $type : host[$host] port[$port] login[$login] base[$db]", $type.'.'._LOG_HS);
217
	}
218
}
219
220
// Premiere connexion au serveur principal:
221
// retourner le charset donnee par la table principale
222
// mais verifier que le fichier de connexion n'est pas trop vieux
223
// Version courante = 0.7 
224
// La version 0.7 indique un serveur d'authentification comme 8e arg
225
// La version 0.6 indique le prefixe comme 7e arg
226
// La version 0.5 indique le serveur comme 6e arg
227
//
228
// La version 0.0 (non numerotee) doit etre refaite par un admin
229
// les autres fonctionnent toujours, meme si :
230
// - la version 0.1 est moins performante que la 0.2
231
// - la 0.2 fait un include_ecrire('inc_db_mysql.php3').
232
233
// http://doc.spip.org/@spip_connect_main
234
function spip_connect_main($connexion)
235
{
236
	if ($GLOBALS['spip_connect_version']< 0.1 AND _DIR_RESTREINT){
237
		include_spip('inc/headers');
238
		redirige_url_ecrire('upgrade', 'reinstall=oui');
239
	}
240
241
	if (!($f = $connexion['select'])) return false;
242
	// en cas d'erreur select retourne la requette (is_string=true donc)
243
	if (!$r = $f('valeur','spip_meta', "nom='charset_sql_connexion'")
244
	  OR is_string($r))
245
		return false;
246
	if (!($f = $connexion['fetch'])) return false;
247
	$r = $f($r);
248
	return ($r['valeur'] ? $r['valeur'] : -1);
249
}
250
251
// compatibilite
252
function spip_connect_ldap($serveur='') {
253
	include_spip('auth/ldap');
254
	return auth_ldap_connect($serveur);
255
}
256
257
// Echappement d'une valeur (num, string, array) sous forme de chaine PHP
258
// pour un array(1,'a',"a'") renvoie la chaine "'1','a','a\''"
259
// Usage sql un peu deprecie, a remplacer par sql_quote()
260
// http://doc.spip.org/@_q
261
function _q ($a) {
262
	return (is_numeric($a)) ? strval($a) :
263
		(!is_array($a) ? ("'" . addslashes($a) . "'")
264
		 : join(",", array_map('_q', $a)));
265
}
266
267
268
// Recuperer le nom de la table de jointure xxxx sur l'objet yyyy
269
// http://doc.spip.org/@table_jointure
270
function table_jointure($x, $y) {
271
	$trouver_table = charger_fonction('trouver_table', 'base');
272
	$xdesc = $trouver_table(table_objet($x));
273
	$ydesc = $trouver_table(table_objet($y));
274
	$ix = @$xdesc['key']["PRIMARY KEY"];
275
	$iy = @$ydesc['key']["PRIMARY KEY"];
276
	if ($table = $ydesc['tables_jointures'][$ix]) return $table;
277
	if ($table = $xdesc['tables_jointures'][$iy]) return $table;
278
	return '';
279
}
280
281
/**
282
 * Echapper les textes entre ' ' ou " " d'une requete SQL
283
 * avant son pre-traitement
284
 * On renvoi la query sans textes et les textes separes, dans
285
 * leur ordre d'apparition dans la query
286
 *
287
 * @param string $query
288
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string|false|array>.

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...
289
 */
290
function query_echappe_textes($query){
291
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
292
	$query = str_replace(array_keys($codeEchappements), array_values($codeEchappements), $query);
293
	if (preg_match_all("/((['])[^']*(\\2))|(([\"])[^\"]*(\\5))/S",$query,$textes)){
294
		$textes = reset($textes); // indice 0 du match
295
		switch(count($textes)){
296
			case 0:$replace=array();break;
297
			case 1:$replace=array('%1$s');break;
298
			case 2:$replace=array('%1$s','%2$s');break;
299
			case 3:$replace=array('%1$s','%2$s','%3$s');break;
300
			case 4:$replace=array('%1$s','%2$s','%3$s','%4$s');break;
301
			case 5:$replace=array('%1$s','%2$s','%3$s','%4$s','%5$s');break;
302
			default:
303
				$replace = range(1,count($textes));
304
				$replace = '%'.implode('$s,%',$replace).'$s';
305
				$replace = explode(',',$replace);
306
				break;
307
		}
308
		$query = str_replace($textes,$replace,$query);
309
	}
310
	else
311
		$textes = array();
312
313
	return array($query, $textes);
314
}
315
316
/**
317
 * Reinjecter les textes d'une requete SQL a leur place initiale,
318
 * apres traitement de la requete
319
 *
320
 * @param string $query
321
 * @param array $textes
322
 * @return string
323
 */
324
function query_reinjecte_textes($query, $textes){
325
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
326
	# debug de la substitution
327
	#if (($c1=substr_count($query,"%"))!=($c2=count($textes))){
328
	#	spip_log("$c1 ::". $query,"tradquery"._LOG_ERREUR);
329
	#	spip_log("$c2 ::". var_export($textes,1),"tradquery"._LOG_ERREUR);
330
	#	spip_log("ini ::". $qi,"tradquery"._LOG_ERREUR);
331
	#}
332
	switch (count($textes)){
333
		case 0:break;
334
		case 1:$query=sprintf($query,$textes[0]);break;
335
		case 2:$query=sprintf($query,$textes[0],$textes[1]);break;
336
		case 3:$query=sprintf($query,$textes[0],$textes[1],$textes[2]);break;
337 View Code Duplication
		case 4:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3]);break;
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...
338 View Code Duplication
		case 5:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3],$textes[4]);break;
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...
339
		default:
340
			array_unshift($textes,$query);
341
			$query = call_user_func_array('sprintf',$textes);
342
			break;
343
	}
344
345
	$query = str_replace(array_values($codeEchappements), array_keys($codeEchappements), $query);
346
347
	return $query;
348
}
349
350
// Pour compatibilite. Ne plus utiliser.
351
// http://doc.spip.org/@spip_query
352
function spip_query($query, $serveur='') {
353
	global $spip_sql_version;
354
	$f = spip_connect_sql($spip_sql_version, 'query', $serveur, true);
355
	return function_exists($f) ? $f($query, $serveur) : false;
356
}
357
358
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
359