File: valider_xml.php

package info (click to toggle)
spip 3.0.17-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 30,776 kB
  • sloc: php: 200,550; xml: 4,367; sh: 272; makefile: 39
file content (301 lines) | stat: -rw-r--r-- 10,529 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('inc/presentation');
include_spip('public/debusquer');

// Script de validation XML selon une DTD
// l'argument var_url peut indiquer un fichier ou un repertoire
// l'argument ext peut valoir "php" ou "html"
// Si "php", le script est execute et la page valide
// Si "html", on suppose que c'est un squelette dont on devine les args
// en cherchant les occurrences de Pile[0].
// Exemples:
// ecrire?exec=valider_xml&var_url=exec&ext=php pour tester l'espace prive
// ecrire?exec=valider_xml&var_url=../squelettes-dist&ext=html pour le public

// http://doc.spip.org/@exec_valider_xml_dist
function exec_valider_xml_dist()
{
	if (!autoriser('sauvegarder')) {
		include_spip('inc/minipres');
		echo minipres();
	} else valider_xml_ok(_request('var_url'), _request('ext'), intval(_request('limit')), _request('recur'));
}

// http://doc.spip.org/@valider_xml_ok
function valider_xml_ok($url, $req_ext, $limit, $rec)
{
	$url = urldecode($url);
	$rec = !$rec ? false : array();
	if (!$limit) $limit = 200;
	$titre = _T('analyse_xml');
	if (!$url) {
		$url_aff = 'http://';
		$onfocus = "this.value='';";
		$texte = $bandeau = $err = '';
	} else {
		include_spip('inc/distant');

		if (is_dir($url)) {
			$dir = (substr($url,-1,1) === '/') ? $url : "$url/";
			$ext = !preg_match('/^[.*\w]+$/', $req_ext) ? 'php' : $req_ext;
			$files = preg_files($dir,  "$ext$", $limit, $rec);
			if (!$files AND $ext!=='html') {
				$files = preg_files($dir, 'html$', $limit, $rec);
				if ($files) $ext = 'html';
			}
			if ($files) {
				$res = valider_dir($files, $ext, $url);
				list($err, $res) = valider_resultats($res, $ext === 'html');
				$err = ' (' . $err . '/' . count($files) .')';
			} else {
				$res = _T('texte_vide');
				$err = '';
			}
			$bandeau = $dir . '*' . $ext . $err;
		} else {
			if (preg_match('@^((?:[.]/)?[^?]*)[?]([0-9a-z_]+)=([^&]*)(.*)$@', $url, $r)) {
			  list(,$server, $dir, $script, $args) = $r;
				if (((!$server) OR ($server == './') 
				    OR strpos($server, url_de_base()) === 0)
				    AND is_dir($dir)) {
				  $url = $script;
				  // Pour quand le validateur saura simuler 
				  // une query-string...
				  // $args = preg_split('/&(amp;)?[a-z0-9_]+=/', $args);
				  $args = true;
				}
			} else { $dir = 'exec'; $script = $url; $args = true;}

			$transformer_xml = charger_fonction('valider', 'xml');
			$onfocus = "this.value='" . addslashes($url) . "';";
			if (preg_match(',^[a-z][0-9a-z_]*$,i', $url)) {
				$res = $transformer_xml(charger_fonction($url, $dir), $args);
				$url_aff = valider_pseudo_url($dir, $script);
			} else {
				$res = $transformer_xml(recuperer_page($url));
				$url_aff = entites_html($url);
			}
			list($texte, $err) = emboite_texte($res);
			if (!$err) {
				$err = '<h3>' . _T('spip_conforme_dtd') . '</h3>';
			}

			$res =
			"<div style='text-align: center'>" . $err . "</div>" .
			"<div style='margin: 10px; text-align: left'>" . $texte . '</div>';
			$bandeau = "<a href='$url_aff'>$url</a>";
		}
	}

	$commencer_page = charger_fonction('commencer_page', 'inc');
	$debut = $commencer_page($titre);
	$jq = http_script("", 'jquery.js');
	
	echo str_replace('<head>', "<head>$jq", $debut);
	$onfocus = '<input type="text" size="70" value="' .$url_aff .'" name="var_url" id="var_url" onfocus="'.$onfocus . '" />';
	$onfocus = generer_form_ecrire('valider_xml', $onfocus, " method='get'");

	echo "<h1>", $titre, '<br>', $bandeau, '</h1>',
	  "<div style='text-align: center'>", $onfocus, "</div>",
	  $res,
	  fin_page();
}

// http://doc.spip.org/@valider_resultats
function valider_resultats($res, $mode)
{
	$i = $j = 0;
	$table = '';
	rsort($res);
	foreach($res as $l) {
		$i++;
		$class = 'row_'.alterner($i, 'even', 'odd');
		list($nb, $texte, $erreurs, $script, $appel, $temps) = $l;
		if ($texte < 0) {
			$texte = (0- $texte);
			$color = ";color: red";
		} else  {$color = '';}

		$err = (!intval($nb)) ? '' : 
		  ($erreurs[0][0] . ' ' . _T('ligne') . ' ' .
		   $erreurs[0][1] .($nb==1? '': '  ...'));
		if ($err) $j++;
		$h = $mode
		? ($appel . '&var_mode=debug&var_mode_affiche=validation')
		: generer_url_ecrire('valider_xml', "var_url=" . urlencode($appel));
		
		$table .= "<tr class='$class'>"
		. "<td style='text-align: right'>$nb</td>"
		. "<td style='text-align: right$color'>$texte</td>"
		. "<td style='text-align: right'>$temps</td>"
		. "<td style='text-align: left'>$err</td>"
		. "<td>$script</td>"
		. "<td><a href='$h'>$appel</a></td>";
	}
	return array($j, "<table class='spip'>"
	  . "<tr><th>" 
	  . _T('erreur_texte')
	  . "</th><th>" 
	  . _T('taille_octets', array('taille' => ' '))
	  . "</th><th>"
	  . _T('zbug_profile', array('time' =>''))
	  . "</th><th>"
	  . _T('message')
	  . "</th><th>Page</th><th>args"
	  . "</th></tr>"
	  . $table
		     . "</table>");
}

// http://doc.spip.org/@valider_script
function valider_script($transformer_xml, $script, $dir, $ext)
{
	$script = basename($script, '.php');
	$dir = basename($dir);
	$f = charger_fonction($script, $dir, true);
// ne pas se controler soi-meme ni l'index du repertoire ni un fichier annexe
	if ($script == _request('exec') OR $script=='index' OR !$f)
		return array('/', 0, '', $script,''); 

	$val = $transformer_xml($f, true);
	$appel = '';
	
	// s'il y a l'attribut minipres, le test est non significatif
	// le script necessite peut-etre des arguments, on lui en donne,
	// en appelant la fonction _args associee si elle existe
	// Si ca ne marche toujours pas, les arguments n'taient pas bons
	// ou c'est une authentification pour action d'administration;
	// tant pis, on signale le cas par un resultat negatif

	if (strpos($val->page, "id='minipres'")) {
		if (!$g = charger_fonction($script . '_args', $dir, true)) {
			$res = 0 - strlen($val->page);
		} else {
			$args = array(1, 'id_article', 1);
			$val = $transformer_xml($g, $args);
			$appel = 'id_article=1&type=id_article&id=1';
			if (strpos($val->page, "id='minipres'")) {
				$res = 0 - strlen($val->page);
			} else $res = strlen($val->page);
		}
	} else $res = strlen($val->page);

	$appel = valider_pseudo_url($dir, $script, $appel);
	$err = $val->err;
	return array(count($err), $res, $err, $script, $appel);
}

// http://doc.spip.org/@valider_pseudo_url
function valider_pseudo_url($dir, $script, $args='')
{
	return  ($dir == 'exec')
	? generer_url_ecrire($script, $args, false, true)
	: ("./?$dir=$script" . ($args ? "&$args" : ''));
}

// On essaye de valider un texte meme sans Doctype
// a moins qu'un Content-Type dise clairement que ce n'est pas du XML
// http://doc.spip.org/@valider_skel
function valider_skel($transformer_xml, $file, $dir, $ext)
{
	if (!lire_fichier ($file, $text)) return array('/', '/', $file,''); 
	if (!strpos($text, 'DOCTYPE')) {
		preg_match(",Content[-]Type: *\w+/(\S)+,", $text, $r);
		if ($r[1] === 'css' OR $r[1] === 'plain')
			return array('/', 'DOCTYPE?', $file,'');
	}

	if ($ext != 'html') {
		// validation d'un non squelette
		$page = array('texte' => $text);
		$url = url_de_base() . _DIR_RESTREINT_ABS . $file;
		$script = $file;
	} else {
		$script = basename($file,'.html');
		// pas de validation solitaire pour les squelettes internes, a revoir.
		if (substr_count($dir, '/') <= 1) {
			$url = generer_url_public($script, $contexte);
		} else 	$url = '';
		$composer = charger_fonction('composer', 'public');
		list($skel_nom, $skel_code) = $composer($text, 'html', 'html', $file);

		spip_log("compilation de $file en " . strlen($skel_code) .  " octets de nom $skel_nom");
		if (!$skel_nom) return array('/', '/', $file,''); 
		$contexte = valider_contexte($skel_code, $file);
		$page = $skel_nom(array('cache'=>''), array($contexte));
	}
	$res = $transformer_xml($page['texte']);
	return array(count($res->err), strlen($res->page), $res->err, $script, $url);
}

// Analyser le code pour construire un contexte plausible complet
// i.e. ce qui est fourni par $Pile[0]
// en eliminant les exceptions venant surtout des Inclure
// Il faudrait trouver une typologie pour generer un contexte parfait:
// actuellement ca produit parfois des erreurs SQL a l'appel de $skel_nom
// http://doc.spip.org/@valider_contexte
function valider_contexte($code, $file)
{
	static $exceptions = array('action', 'doublons', 'lang');
	preg_match_all('/(\S*)[$]Pile[[]0[]][[].(\w+).[]](\S*)/', $code, $r, PREG_SET_ORDER);
	$args = array();
	// evacuer les repetitions et les faux parametres
	foreach($r as $v) {
		list(,$f, $nom, $suite) = $v;
		if (!in_array($nom, $exceptions)
		AND (!isset($args[$nom]) OR !$args[$nom]))
			$args[$nom] = ((strpos($f, 'sql_quote') !== false)
				AND strpos($suite, "'int'") !==false);
	}
	$contexte= array(); // etudier l'ajout de:
	// 'lang' => $GLOBALS['spip_lang'],
	// 'date' => date('Y-m-d H:i:s'));
	foreach ($args as $nom => $f) {
		if (!$f)
		  $val = 'id_article';
		else {
		  // on suppose que arg numerique => primary-key d'une table
		  // chercher laquelle et prendre un numero existant
		  $val = 0;
		  $type = (strpos($nom, 'id_') === 0)  ? substr($nom,3) : $nom;
		  $trouver_table = charger_fonction('trouver_table', 'base');
		  $table = $trouver_table(table_objet_sql($type));
		  if ($table)
		    $val = @sql_getfetsel($nom, $table['table'], '', '','',"0,1");
		    // porte de sortie si ca marche pas, 
		  if (!$val) $val = 1; 
		}
		$contexte[$nom] =  $val;
	}
	return $contexte;
}

// http://doc.spip.org/@valider_dir
function valider_dir($files, $ext, $dir)
{
	$res = array();
	$transformer_xml = charger_fonction('valider', 'xml');
	$valideur = $ext=='php' ? 'valider_script' : 'valider_skel' ;
	foreach($files as $f) {
		spip_timer($f);
		$val = $valideur($transformer_xml, $f, $dir, $ext);
		$n = spip_timer($f); 
		$val[]= $n;
		spip_log("validation de $f en $n secondes");
		$res[]= $val;
	}
	return $res;
}
?>