X-Git-Url: http://git.cyclocoop.org/?p=velocampus%2Fweb%2Fwww.git;a=blobdiff_plain;f=www%2Fecrire%2Fpublic%2Fdebusquer.php;fp=www%2Fecrire%2Fpublic%2Fdebusquer.php;h=7fa10dc811a17efa90d597044d76af8f241b090f;hp=0000000000000000000000000000000000000000;hb=80b4d3e85f78d402ed2e73f8f5d1bf4c19962eed;hpb=aaf970bf4cdaf76689ecc10609048e18d073820c diff --git a/www/ecrire/public/debusquer.php b/www/ecrire/public/debusquer.php new file mode 100644 index 0000000..7fa10dc --- /dev/null +++ b/www/ecrire/public/debusquer.php @@ -0,0 +1,617 @@ + erreur) +// et volontaires (var_mode et var_profile) +// Si pas d'autorisation, les erreurs ne sont pas affichees +// (mais seront dans les logs) +// Si l'erreur vient de SPIP, en parler sur spip@rezo.net + +function public_debusquer_dist($message='', $lieu='') { + global $visiteur_session; + global $debug_objets; + static $tableau_des_erreurs = array(); + + // Erreur ou appel final ? + if ($message) { + $message = debusquer_compose_message($message); + $tableau_des_erreurs[] = array($message, $lieu); + set_request('var_mode', 'debug'); + $GLOBALS['bouton_admin_debug'] = true; + // Permettre a la compil de continuer + if (is_object($lieu) AND !$lieu->code) + $lieu->code = "''"; + // forcer l'appel au debusqueur en cas de boucles infernales + $urgence = (_DEBUG_MAX_SQUELETTE_ERREURS AND count($tableau_des_erreurs) > _DEBUG_MAX_SQUELETTE_ERREURS); + if (!$urgence) return; + } + if (empty($debug_objets['principal'])) + $debug_objets['principal'] = $GLOBALS['fond']; + + include_spip('inc/autoriser'); + if (!autoriser('debug')) return; + include_spip('inc/headers'); + include_spip('inc/filtres'); + + // en cas de squelette inclus, virer le code de l'incluant: + // - il contient souvent une Div restreignant la largeur a 3 fois rien + // - ca fait 2 headers ! + // sauf si l'on se trouve deja dans un flux compresse (plugin compresseur + // actif par exemple) + if (ob_get_length() + AND + !in_array('ob_gzhandler', ob_get_status())) { + ob_end_clean(); + } + + lang_select($visiteur_session['lang']); + $fonc = _request('var_mode_objet'); + $mode = _request('var_mode_affiche'); + $self = str_replace("\\'", ''', self()); + $self = parametre_url($self,'var_mode', 'debug'); + + $res = debusquer_bandeau($tableau_des_erreurs) + . '
' + . debusquer_squelette($fonc, $mode, $self); + + if (!_DIR_RESTREINT OR headers_sent()) return $res; + if ($tableau_des_erreurs) http_status(503); + + http_no_cache(); + if (isset($_GET['var_profile'])) { + $titre = parametre_url($GLOBALS['REQUEST_URI'], 'var_profile', ''); + $titre = parametre_url($titre, 'var_mode', ''); + } else { + if (!$fonc) $fonc = $debug_objets['principal']; + $titre = !$mode ? $fonc : ($mode . ' ' . $debug_objets['sourcefile'][$fonc]); + } + if ($message===false) { + lang_select(); + return debusquer_entete($titre, $res); + } + else + echo debusquer_entete($titre, $res); + exit; +} + +function debusquer_compose_message($msg) +{ + if (is_array($msg)) { + if (!is_numeric($msg[0])) + // message avec argument: instancier + $msg = _T($msg[0], $msg[1], 'spip-debug-arg'); + else + // message SQL: interpreter + $msg = debusquer_requete($msg); + } + spip_log("Debug: " . $msg . " (" . $GLOBALS['fond'] .")" ); + return $msg; +} + +function debusquer_bandeau($erreurs) { + + if (!empty($erreurs)) { + $n = count($erreurs) . ' ' . _T('zbug_erreur_squelette'); + return debusquer_navigation($erreurs, $n); + } elseif (!empty($GLOBALS['tableau_des_temps'])) { + include_spip('public/tracer'); + list($temps, $nav) = chrono_requete($GLOBALS['tableau_des_temps']); + return debusquer_navigation($temps, $nav, 'debug-profile'); + } else return ''; + } + +function debusquer_contexte($env) { + + if (is_array($env_tab = @unserialize($env))) $env = $env_tab; + + if (!$env) return ''; + $res = ""; + foreach ($env as $nom => $valeur) { + if (is_array($valeur)) + $valeur = '(' . count($valeur) .' items) [' . join(',', $valeur) . ']'; + $res .= "\n".nl2br(entites_html($nom)) + . ": ".nl2br(entites_html($valeur)) + . "\n"; + } + + return "
#ENV\n
$res
\n"; +} + +// Affichage du tableau des erreurs ou des temps de calcul +// Cliquer sur les numeros en premiere colonne permet de voir le code + +function debusquer_navigation($tableau, $caption='', $id='debug-nav') { + + if (_request('exec')=='valider_xml') return ''; + $GLOBALS['bouton_admin_debug'] = true; + $res = ''; + $href = quote_amp(parametre_url($GLOBALS['REQUEST_URI'], 'var_mode', 'debug')); + foreach ($tableau as $i => $err) { + $boucle = $ligne = $skel = ''; + list($msg, $lieu) = $err; + if (is_object($lieu)) { + $ligne = $lieu->ligne; + $boucle = $lieu->id_boucle ? $lieu->id_boucle : ''; + if (isset($lieu->descr['nom'])) { + $nom_code = $lieu->descr['nom']; + $skel = $lieu->descr['sourcefile']; + $h2 = parametre_url($href, 'var_mode_objet', $nom_code); + $h3 = parametre_url($h2, 'var_mode_affiche', 'squelette') . '#L' . $ligne; + $skel = "$skel"; + if ($boucle) { + $h3 = parametre_url($h2.$boucle, 'var_mode_affiche', 'boucle'); + $boucle = "$boucle"; + } + } + } + + $j = ($i+1); + $res .= "" + . $j + . " " + . $msg + . "" + . ($skel ? $skel : "   /  ") + . "" + . ($boucle ? $boucle : "   /  ") + . "" + . $ligne + . "\n"; + + } + + return "\n" + . "" + . "" + . $res + . "
" + . $caption +## aide locale courte a ecrire, avec lien vers une grosse page de documentation +# aide('erreur_compilation'), + . "
" + . _T('numero') + . "" + . _T('message') + . "" + . _T('squelette') + . "" + . _T('boucle') + . "" + . _T('ligne') + . "
"; +} + +// +// Si une boucle cree des soucis, on peut afficher la requete fautive +// avec son code d'erreur +// + +function debusquer_requete($message) { + list($errno, $msg, $query) = $message; + if (preg_match(',err(no|code):?[[:space:]]*([0-9]+),i', $msg, $regs)) + { + $errno = $regs[2]; + + } else if (($errno == 1030 OR $errno <= 1026) + AND preg_match(',[^[:alnum:]]([0-9]+)[^[:alnum:]],', $msg, $regs)) + $errno = $regs[1]; + + // Erreur systeme + if ($errno > 0 AND $errno < 200) { + $retour = "

" + . _T('info_erreur_systeme', array('errsys'=>$errno)) + . "
\n" + . _T('info_erreur_systeme2', + array('script' => generer_url_ecrire('admin_repair'))) + . '
'; + spip_log("Erreur systeme $errno"); + return array($retour,''); + } + // Requete erronee + + $err = ""._T('avis_erreur_mysql')." $errno
\n" + . htmlspecialchars($msg) + . "\n
" + . htmlspecialchars($query) + . "

" + ;//. aide('erreur_mysql'); + + return $err; +} + +// http://doc.spip.org/@trouve_boucle_debug +function trouve_boucle_debug($n, $nom, $debut=0, $boucle = "") +{ + global $debug_objets; + + $id = $nom . $boucle; + if (is_array($debug_objets['sequence'][$id])) { + foreach($debug_objets['sequence'][$id] as $v) { + + if (!preg_match('/^(.*)(<\?.*\?>)(.*)$/s', $v[0],$r)) + $y = substr_count($v[0], "\n"); + else { + if ($v[1][0] == '#') + // balise dynamique + $incl = $debug_objets['resultat'][$v[2]]; + else + // inclusion + $incl = $debug_objets['squelette'][trouve_squelette_inclus($v[0])]; + $y = substr_count($incl, "\n") + + substr_count($r[1], "\n") + + substr_count($r[3], "\n"); + } + if ($n <= ($y + $debut)) { + if ($v[1][0] == '?') + return trouve_boucle_debug($n, $nom, $debut, substr($v[1],1)); + elseif ($v[1][0] == '!') { + if ($incl = trouve_squelette_inclus($v[1])) + return trouve_boucle_debug($n, $incl, $debut); + } + return array($nom, $boucle, $v[2] -1 + $n - $debut ); + } + $debut += $y; + } + } + return array($nom, $boucle, $n-$debut); +} + +// http://doc.spip.org/@trouve_squelette_inclus +function trouve_squelette_inclus($script) +{ + global $debug_objets; + preg_match('/include\(.(.*).php3?.\);/', $script, $reg); + // si le script X.php n'est pas ecrire/public.php + // on suppose qu'il prend le squelette X.html (pas sur, mais y a pas mieux) + if ($reg[1] == 'ecrire/public') + // si c'est bien ecrire/public on cherche le param 'fond' + if (!preg_match("/'fond' => '([^']*)'/", $script, $reg)) + // a defaut on cherche le param 'page' + if (!preg_match("/'param' => '([^']*)'/", $script, $reg)) + $reg[1] = "inconnu"; + $incl = $reg[1] . '.' . _EXTENSION_SQUELETTES . '$'; + + foreach($debug_objets['sourcefile'] as $k => $v) { + if (preg_match(",$incl,",$v)) return $k; + } + return ""; +} + +// http://doc.spip.org/@reference_boucle_debug +function reference_boucle_debug($n, $nom, $self) +{ + list($skel, $boucle, $ligne) = trouve_boucle_debug($n, $nom); + + if (!$boucle) + return !$ligne ? "" : + (" (" . + (($nom != $skel) ? _T('squelette_inclus_ligne') : + _T('squelette_ligne')) . + " $ligne)"); + else { + $self .= "&var_mode_objet=$skel$boucle&var_mode_affiche=boucle"; + + return !$ligne ? " (boucle\n$boucle)" : + " (boucle $boucle ligne\n$ligne)"; + } +} + +// affiche un texte avec numero de ligne et ancre. + +// http://doc.spip.org/@ancre_texte +function ancre_texte($texte, $fautifs=array(), $nocpt=false) +{ + $var_mode_ligne = _request('var_mode_ligne'); + if ($var_mode_ligne) $fautifs[]= array($var_mode_ligne); + $res =''; + + $s = highlight_string(str_replace('','',$texte),true); + + $s = str_replace('/@@@@@','/script', // bug de highlight_string + str_replace('','', + str_replace('') { $s=substr($s,6); $res = '';} + + $s = preg_replace(',<(\w[^<>]*)>([^<]*)
([^<]*),', + '<\1>\2
' . "\n" . '<\1>\3', + $s); + + + $tableau = explode("
", $s); + + $format = "%0" . strval(@strlen(count($tableau))). "d %s
\n"; + + $format10=str_replace('white','lightgrey',$format); + $formaterr="color: red;"; + $i=1; + $flignes = array(); + $loc = array(0,0); + foreach ($fautifs as $lc) + if (is_array($lc)) { + $l = array_shift($lc); + $flignes[$l] = $lc; + } else $flignes[$lc] = $loc; + + $ancre = md5($texte); + foreach ($tableau as $ligne) { + if (isset($flignes[$i])) { + $ligne = str_replace(' ',' ', $ligne); + $indexmesg = $flignes[$i][1]; + $err = textebrut($flignes[$i][2]); + // tentative de pointer sur la colonne fautive; + // marche pas car highlight_string rajoute des entites. A revoir. + // $m = $flignes[$i][0]; + // $ligne = substr($ligne, 0, $m-1) . + // sprintf($formaterr, substr($ligne,$m)); + $bg = $formaterr; + } else {$indexmesg = $ancre; $err= $bg='';} + $res .= sprintf((($i%10) ? $format :$format10), $i, $bg, $indexmesg, $err, $i, $ligne); + $i++; + } + + return "
" + .'
' + . ($nocpt ? '' : _T('info_numero_abbreviation')) + . "
+ ".$res."
\n"; +} + +// l'environnement graphique du debuggueur + +function debusquer_squelette ($fonc, $mode, $self) { + global $debug_objets; + + if ($mode !== 'validation') { + if ($debug_objets['sourcefile']) { + $res = "
\n" + . debusquer_navigation_squelettes($self) + . "
"; + } else $res = ''; + if ($fonc) { + $id = " id='$fonc'"; + if (!empty($GLOBALS['debug_objets'][$mode][$fonc])) { + list($legend, $texte, $res2) = debusquer_source($fonc, $mode); + $texte .= $res2; + } elseif (!empty($debug_objets[$mode][$fonc . 'tout'])) { + $legend = _T('zbug_' . $mode); + $texte = $debug_objets[$mode][$fonc . 'tout']; + $texte = ancre_texte($texte, array('','')); + } + } else return strlen(trim($res)) + ? "
$res
" + // cas de l'appel sur erreur: montre la page + : $GLOBALS['debug_objets']['resultat']['tout']; + } else { + $valider = charger_fonction('valider', 'xml'); + $val = $valider($debug_objets['validation'][$fonc . 'tout']); + // Si erreur, signaler leur nombre dans le formulaire admin + $debug_objets['validation'] = $val[1] ? count($val[1]):''; + list($texte, $err) = emboite_texte($val, $fonc, $self); + if ($err === false) + $err = _T('impossible'); + elseif ($err === true) + $err = _T('correcte'); + else $err = ": $err"; + $legend = _T('validation') . ' ' . $err; + $res = $id = ''; + } + return !trim($texte) ? '' : ( + "
$res" + . "
" + . $legend + . "" + . $texte + . "
" + . "
"); +} + +function debusquer_navigation_squelettes($self) +{ + global $debug_objets, $spip_lang_right; + + $res = ''; + $boucles = !empty($debug_objets['boucle']) ? $debug_objets['boucle']:''; + $contexte = $debug_objets['contexte']; + $t_skel = _T('squelette'); + foreach ($debug_objets['sourcefile'] as $nom => $sourcefile) { + $self2 = parametre_url($self,'var_mode_objet', $nom); + $nav = !$boucles ? '' : debusquer_navigation_boucles($boucles, $nom, $self); + $temps = !isset($debug_objets['profile'][$sourcefile]) ? '' : _T('zbug_profile', array('time'=>$debug_objets['profile'][$sourcefile])); + + $res .= "
" + . $t_skel + . ' ' + . $sourcefile + ." :\n" + . $t_skel + . "\n" + . _T('zbug_resultat') + . "\n" + . _T('zbug_code') + ."\n" + . _T('zbug_calcul') + . "" + . (!$temps ? '' : ("\n$temps
")) + . debusquer_contexte($contexte[$sourcefile]) + . (!$nav ? '' : ("\n$nav
\n")) + . "
\n"; + } + return $res; +} + +function debusquer_navigation_boucles($boucles, $nom_skel, $self) +{ + $i = 0; + $res = ''; + $var_mode_objet = _request('var_mode_objet'); + foreach ($boucles as $objet => $boucle) { + if (substr($objet, 0, strlen($nom_skel)) == $nom_skel) { + $i++; + $nom = $boucle->id_boucle; + $req = $boucle->type_requete; + $crit = decompiler_criteres($boucle->param, $boucle->criteres); + $self2 = $self . "&var_mode_objet=" . $objet; + + $res .= "\n$i\n" . + "" . + _T('zbug_boucle') . + "\n" . + _T('zbug_resultat') . + "\n" . + _T('zbug_code') . + "\n" . + _T('zbug_calcul') . + "\n" . + (($var_mode_objet == $objet) ? "$nom" : $nom) . + "\n" . + $req . + "\n" . + $crit . + ""; + } + } + return $res; +} + +function debusquer_source($objet, $affiche) +{ + $quoi = $GLOBALS['debug_objets'][$affiche][$objet]; + $nom = $GLOBALS['debug_objets']['boucle'][$objet]->id_boucle; + $res2 = ""; + + if ($affiche == 'resultat') { + $legend = $nom; + $req = $GLOBALS['debug_objets']['requete'][$objet]; + if (function_exists('traite_query')) { + $c = strtolower(_request('connect')); + $c = $GLOBALS['connexions'][$c ? $c : 0]['prefixe']; + $req = traite_query($req,'', $c); + } + // permettre le copier/coller facile + // $res = ancre_texte($req, array(), true); + $res = "
\n
\n" . $req . "
\n
\n"; + // formatage et affichage des resultats bruts de la requete + $ress_req = spip_query($req); + $brut_sql = ''; + $num = 1; + // eviter l'affichage de milliers de lignes + // personnalisation possible dans mes_options + $max_aff = defined('_MAX_DEBUG_AFF') ? _MAX_DEBUG_AFF : 50; + while ($retours_sql = sql_fetch($ress_req)) { + if ($num <= $max_aff) { + $brut_sql .= "

" .($num == 1 ? $num. " sur " .sql_count($ress_req):$num). "

"; + $brut_sql .= "

"; + foreach ($retours_sql as $key => $val) { + $brut_sql .= "" .$key. " => " .htmlspecialchars(couper($val, 150)). "
\n"; + } + $brut_sql .= "

"; + } + $num++; + } + $res2 = interdire_scripts($brut_sql); + foreach ($quoi as $view) { + // ne pas afficher les $contexte_inclus + $view = preg_replace(",<\?php.+\?[>],Uims", "", $view); + if ($view) { + $res2 .= "\n
" .interdire_scripts($view). "
"; + } + } + + } else if ($affiche == 'code') { + $legend = $nom; + $res = ancre_texte("<"."?php\n".$quoi."\n?".">"); + } else if ($affiche == 'boucle') { + $legend = _T('boucle') . ' ' . $nom; + $res = ancre_texte(decompiler_boucle($quoi)); + } else if ($affiche == 'squelette') { + $legend = $GLOBALS['debug_objets']['sourcefile'][$objet]; + $res = ancre_texte($GLOBALS['debug_objets']['squelette'][$objet]); + } + + return array($legend, $res, $res2); +} + +// http://doc.spip.org/@debusquer_entete +function debusquer_entete($titre, $corps) +{ + global $debug_objets; + include_spip('balise/formulaire_admin'); + include_spip('public/assembler'); // pour inclure_balise_dynamique + include_spip('inc/texte'); // pour corriger_typo + + return _DOCTYPE_ECRIRE . + html_lang_attributes() . + "\n" . + ('SPIP ' . $GLOBALS['spip_version_affichee'] . ' ' . + _T('admin_debug') . ' ' . $titre . ' (' . + supprimer_tags(corriger_typo($GLOBALS['meta']['nom_site']))) . + ")\n" . + "\n" . + http_script('', 'jquery.js') + . "" . + "\n" . + "\n" . + "
" . + $corps . + inclure_balise_dynamique(balise_FORMULAIRE_ADMIN_dyn('spip-admin-float', $debug_objets), false) . + '
'; +} + +?>