You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1608 lines
58 KiB

<?php
/*
+----------------------------------------------------------------------+
| APC |
+----------------------------------------------------------------------+
| Copyright (c) 2006-2011 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors du apcu.php d'origine : |
| Ralf Becker <beckerr@php.net> |
| Rasmus Lerdorf <rasmus@php.net> |
| Ilia Alshanetsky <ilia@prohost.org> |
| Auteur des adaptations et du plugin SPIP : |
| JLuc http://contrib.spip.net/JLuc |
+----------------------------------------------------------------------+
All other licensing and usage conditions are those of the PHP Group.
*/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
include_spip ('inc/autoriser');
if (!autoriser('xray')) {
die("Autorisation non accordée : devenez webmestre d'abord ou obtenez un accès.");
}
include_spip('inc/filtres');
include_spip('inc/cachelab');
include('inc/xray_utilise.php');
include('inc/xray.php');
global $meta_derniere_modif;
$meta_derniere_modif = lire_config('derniere_modif');
$VERSION = '$Id$';
////////// READ OPTIONAL CONFIGURATION FILE ////////////
if (file_exists("apc.conf.php")) {
include ("apc.conf.php");
}
////////////////////////////////////////////////////////
////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
defaults('MAXLEN_HTMLCOURT', 1000); // Couper les html
// (beckerr) I'm using a clear text password here, because I've no good idea how to let
// users generate a md5 or crypt password in a easy way to fill it in above
defaults('DATE_FORMAT', 'Y-m-d H:i:s');
defaults('GRAPH_SIZE', 400); // Image size
// defaults('PROXY', 'tcp://127.0.0.1:8080');
/**
* _CACHE_NAMESPACE est défini par memoization et préfixe chaque nom de cache SPIP
* On ne souhaite pas que cette partie du nom s'affiche sur chaque ligne
* */
if (!defined ('XRAY_NEPASAFFICHER_DEBUTNOMCACHE')) {
define ('XRAY_NEPASAFFICHER_DEBUTNOMCACHE', true);
}
/**
* Par défaut on ne veut QUE afficher les caches du site courant
*/
if (!defined('XRAY_NEPASAFFICHER_AUTRES_SITES')) {
define ('XRAY_NEPASAFFICHER_AUTRES_SITES', true);
}
////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
include_spip ('inc/xray_stats');
// Strings utils
function ajuste_longueur_html(string $str) : string {
$court = (!isset($_GET['ZOOM']) or ($_GET['ZOOM'] != 'TEXTELONG'));
$str = trim(preg_replace("/^\s*$/m", '', $str)); // enlève lignes vides... mais il en reste qqunes
if ($court and (mb_strlen($str) > MAXLEN_HTMLCOURT))
$str = mb_substr($str, 0, MAXLEN_HTMLCOURT) . '...';
elseif (!$str)
$str = '(vide)';
return $str;
}
function is_serialized($str): bool {
return ($str == serialize(false) || @unserialize($str) !== false);
}
function get_apc_data(string $info, ?bool &$data_success) {
if (apcu_exists($info)
and ($data = apcu_fetch($info, $data_success))
and $data_success
and is_array($data) and (count($data) == 1)
and is_serialized($data[0])
) {
$page = unserialize($data[0]);
if (is_array($page)) {
gunzip_page ($page);
}
return $page;
}
$data_success = false;
return null;
}
function explique_echec (string $info) {
if (!apcu_exists($info)) {
return "doesnt exist";
}
$data = apcu_fetch($info, $data_success);
if (!$data) {
return "empty fetch result";
}
if (!$data_success) {
return "fetch failed";
}
if (!is_array($data)) {
return "fetch result not an array pour $info.<br>Contenu = <xmp>" . substr (print_r ($data, 1), 0,
300) . '</xmp>';
}
if (count($data) != 1) {
return "fetch result not a singleton : <xmp>" . substr (print_r ($data, 1), 0, 300) . "</xmp>";
}
if (!$data[0]) {
return "fetch result is empty";
}
if (!is_serialized($data[0])) {
return "fetch content isnt serialized : <xmp>" . substr (print_r ($data[0], 1), 0, 300) . "</xmp>";
}
return "Should be ok !";
}
function joli_contexte($contexte) {
global $MY_SELF;
$return = '';
if (!$contexte)
return '';
if (!is_array($contexte))
return $contexte;
foreach ($contexte as $var => $val) {
$print = print_r ($val, 1);
if (is_array ($val)
or (is_string ($val) and strpos ($val, "\n") !== false)) {
$return .= "<xmp>[$var] => (" . gettype ($val) . ") $print</xmp>";
} else {
if (!is_string ($val)) {
$val = '(' . gettype ($val) . ')' . ((string)$val); // utilité hypothétique
}
$ligne = "[$var] => $val";
if (strlen ($val) < 100) {
$url = parametre_url (parametre_url ($MY_SELF, 'WHERE', 'CONTEXTE'),
'SEARCH', "$var=$val");
$title = "Voir tous les caches ayant cette même valeur de contexte";
$return .= "<a class='lien_contexte' href='$url' title='$title'><xmp>$ligne</xmp></a>";
if (intval ($val) and (substr ($var, 0, 3) == 'id_')) {
$return .= bouton_objet (substr ($var, 3), intval ($val), $contexte);
}
} else {
$return .= "<xmp>$ligne</xmp>";
}
$return .= "<br>";
}
}
return $return;
}
/**
* @param $extra le cache
* @return string son affichage jolifié : taille adaptée, liens activés
*/
function xray_joli_cache($extra) {
if (is_array($extra)
and isset($extra['texte']))
$extra['texte'] = ajuste_longueur_html($extra['texte']);
// sinon c'est pas un squelette spip, par exemple une textwheel
// ou juste un talon ou juste une des métadonnées du cache
$print=print_r($extra,1);
if (!is_array($extra)) {
return "<xmp>" . ajuste_longueur_html ($print) . "</xmp>";
}
// On enlève 'Array( ' au début et ')' à la fin
$print = trim(substr($print, 5), " (\n\r\t");
$print = substr ($print, 0, -1);
// rien à améliorer s'il n'y a ni la source ni le squelette
if (!isset($extra['source']) and !isset($extra['squelette'])) {
return "<xmp>$print</xmp>";
}
// [squelette] => html_5731a2e40776724746309c16569cac40
// et [source] => plugins/paeco/squelettes/inclure/element/tag-rubrique.html
$print = preg_replace_callback("/\[(squelette|source)\]\s*=>\s*(html_[a-f0-9]{32}+|[\w_\.\/\-]+\.html)$/im",
function($match){
return '</xmp>'.xray_link_to_file($match[1], $match[2], true).'<xmp>';
},
$print);
$print = preg_replace('/^ /m', '', $print);
return "<xmp>$print</xmp>";
}
/**
* @param string $type 'source' (spip) ou 'squelette' (compilé)
* @param string $chemin chemin vers le fichier tel que stocké dans les caches
* @param bool $avec_type faut il aussi présenter le type ?
* @return string
*/
function xray_link_to_file($type, $chemin, $avec_type) {
if (!defined('_SPIP_ECRIRE_SCRIPT')) {
spip_initialisation_suite (); // pour define(_DIR_CACHE)
}
switch ($type) {
case 'squelette' : // cache squelette intermédiaire, en php
global $self_pour_lien;
$source = trim(_DIR_CACHE, '/').'/skel/'.$chemin.'.php';
if (!file_exists ($source)) {
return '<span style="color:red">'.($avec_type ? '[squelette] => ' : '').$chemin.' a été supprimé</span>';
}
$title = "Squelette compilé : cache intermédiaire en php";
$hdel = parametre_url (parametre_url($self_pour_lien, 'SOURCE', $source), 'action_link', 'del_file');
$more = "<a title='Décalculer le squelette = effacer ce cache compilé' href='$hdel' style='color:red; font-size:x-small; margin-left:1em;'>X</a>";
break;
case 'source' :
$source = '../'.$chemin;
$title = "Source du squelette SPIP, avec boucles, balises etc";
$more = '';
if (
stripos ($source, '/formulaires/')
and file_exists ($source_php = preg_replace('/\.html/i', '.php', $source))
) {
// C'est un formulaire CVT, on présente le lien vers le source PHP
global $self_pour_lien;
$more = "<a class='lien_contexte' title='Source PHP du formulaire CVT'
href='".generer_url_ecrire('xray', "SOURCE=$source_php")."'
target='blank'> CVT <small>&#128279;</small></a>";
}
break;
default :
die ("type = $type inconnu dans xray_link_to_file pour chemin $chemin");
}
$res = ($avec_type ? "[$type] => " : '');
return $res."<a class='lien_contexte' title='$title'
href='".generer_url_ecrire('xray', "SOURCE=$source")."'
target='blank'>$chemin <small>&#128279;</small></a>
$more";
}
/**
* @param string $id_session identifiant d'une session (suite de 8 hexa)
* @param string $url_session lien vers le scan de cette session
* @return string
*/
function bouton_session(string $id_session, string $url_session) {
if (function_exists('cachelab_cibler')) {
$title = cachelab_cibler(
'get_html',
['chemin'=>'xray_marqueur_visible_'.$id_session.'$'],
['clean'=>false]
);
}
else {
$title = 'Installez CacheLab pour bénéficier des informations identitaires sur cette session.';
}
if (!$title or !is_string ($title)) {
$title = "Erreur d'accés au marqueur xray";
}
else {
$title .= "\nVoir tous les caches sessionnés de cet internaute";
$title = preg_replace ("/\n+/", "\n", $title);
}
return "<a href=\"$url_session\" class='lien_suppl' title=\"$title\">[session]</a>";
}
function bouton_objet($objet, $id_objet, $contexte) {
$objet_visible = $objet;
if ($objet == 'secteur')
$objet = 'rubrique';
elseif (($objet == 'objet') and isset ($contexte['objet']))
{
$objet_visible = $objet = $contexte['objet'];
};
return "<a href='/ecrire/?exec=$objet&id_$objet=$id_objet' target='blank'
class='lien_suppl'
title=\"" . attribut_html(generer_info_entite($id_objet, $objet, 'titre', 'etoile')) . "\">
[voir $objet_visible]
</a>
";
}
function antislash ($str) {
return str_replace('/', '\/', $str);
}
define ('XRAY_PATTERN_DEBUTNOMCACHE_MEMOIZATION', '/^(.*):(443|80):([a-f0-9]{8}):/i');
define ('XRAY_PATTERN_DEBUTNOMCACHE_SPIP', '/^(.*):(443|80):([a-f0-9]{8}):cache:/i');
define ('XRAY_PATTERN_SESSION', '/_([a-f0-9]{8}|)$/i');
define ('XRAY_PATTERN_SESSION_AUTH', '/_([a-f0-9]{8})$/i');
define ('XRAY_PATTERN_SESSION_ANON', '/_$/i');
define ('XRAY_PATTERN_NON_SESSION', '/[^_](?<!_[a-f0-9]{8})$/i');
define ('XRAY_PATTERN_TALON', '/^(.*)(?<!_[a-f0-9]{8})(?<!_)(_([a-f0-9]{8})?|)$/i');
/**
* @param $cle clé du cache
* @return string clé pour mémoization
*
* Certaines parties du code de Xray font la supposition qu'il n'y a qu'un seul domaine. Ici par exemple.
* Memoization aussi semble t il.
* Pour gérer plusieurs domaines 'ensemble' il faudrait pfiou un nouveau jeu de méthodes de Memoization ?
*/
function xray_cachekey_to_memoizationkey($cle){
return preg_replace(XRAY_PATTERN_DEBUTNOMCACHE_MEMOIZATION, '', $cle);
}
/**
* @param string $cle
* @return string renvoie le radical du nom du cache = souvent le chemin du squelette
* Ça enlève le préfixe non affiché plus le préfixe md5 et ça supprime le suffixe de session
* MAIS ça ne supprime pas les suffixes /12354 ou /spip ou autres des squelettes appelés en tant que pages
*
*/
function cache_get_radical ($cle) {
// on utilise pas XRAY_NEPASAFFICHER_DEBUTNOMCACHE pour tenir compte des éventuelles variantes de NDD ou de port
$squelette = substr(preg_replace (XRAY_PATTERN_DEBUTNOMCACHE_SPIP, '', $cle), 33);
return preg_replace(XRAY_PATTERN_SESSION, '', $squelette);
}
////////////////////////////////////////////////////////////////////////
// "define if not defined"
function defaults($d, $v) {
if (!defined($d))
define($d, $v); // or just @define(...)
}
// rewrite $PHP_SELF to block XSS attacks
//
$PHP_SELF = isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'], ''), ENT_QUOTES, 'UTF-8') : '';
$time = time();
$host = php_uname('n');
if ($host) {
$host = '(' . $host . ')';
}
if (isset($_SERVER['SERVER_ADDR'])) {
$host .= ' (' . $_SERVER['SERVER_ADDR'] . ')';
}
// operation constants
define('OB_HOST_STATS', 1);
define('OB_USER_CACHE', 2);
define('OB_CACHELAB', 4);
// check validity of input variables
$vardom = array(
'exec' => '/^[a-zA-Z0-9_\-\.]+$/', // pour #URL_ECRIRE{xray}
'OB' => '/^\d+$/', // operational mode switch
'CC' => '/^[01]$/', // clear cache requested
'PP' => '/^[01]$/', // Purger Précache de compilation des squelettes en plus de vider le cache APC user
'DU' => '/^.*$/', // Delete User Key
'SH' => '/^[a-z0-9]*$/', // shared object description
'IMG' => '/^[123]$/', // image to generate
'SOURCE' => '/^[a-zA-Z0-9_\-\.\/]+$/', // file source to display
// 'LO' => '/^1$/', // login requested
'TYPELISTE' => '/^(caches|squelettes)$/',
'COUNT' => '/^\d+$/', // number of line displayed in list
'S_KEY' => '/^[AHSMCDTZQNVI]$/', // first sort key
'SORT' => '/^[DA]$/', // second sort key
'AGGR' => '/^\d+$/', // aggregation by dir level
'SEARCH' => '~.*~',
'TYPECACHE' => '/^(|ALL|NON_SESSIONS|SESSIONS|SESSIONS_AUTH|SESSIONS_NONAUTH|SESSIONS_TALON|FORMULAIRES|DYNAMIQUES|STATIQUES|PAGES|INCLUSIONS)$/', //
'ZOOM' => '/^(|TEXTECOURT|TEXTELONG)$/',
'WHERE' => '/^(|ALL|HTML|CONTEXTE|META|FICHIER_SOURCE|FICHIER_SKEL|INCLUSIONS)$/', // recherche dans le contenu
'EXTRA' => '/^(|CONTEXTE|CONTEXTES_SPECIAUX|HTML_COURT|SQUELETTE|INFO_AUTEUR|INFO_OBJET_SPECIAL|INVALIDEURS|INVALIDEURS_SPECIAUX|INCLUSIONS' // partie dans laquelle se fait la recherche
.(test_plugin_actif('macrosession') ? '|MACROSESSIONS|MACROAUTORISER' : '')
.')$/' // Affichage pour chaque élément de la liste
);
global $MYREQUEST;
$MYREQUEST = array();
// handle POST and GET requests
if (empty($_REQUEST)) {
if (!empty($_GET) && !empty($_POST)) {
$_REQUEST = array_merge($_GET, $_POST);
} else if (!empty($_GET)) {
$_REQUEST = $_GET;
} else if (!empty($_POST)) {
$_REQUEST = $_POST;
} else {
$_REQUEST = array();
}
}
// check parameter syntax
foreach ($vardom as $var => $dom) {
if (!isset($_REQUEST[$var]))
$MYREQUEST[$var] = NULL;
elseif (!is_array($_REQUEST[$var]) && preg_match($dom . 'D', $_REQUEST[$var])) {
$MYREQUEST[$var] = $_REQUEST[$var];
}
else {
echo "<xmp>ERREUR avec parametre d'url « $var » qui vaut « {$_REQUEST[$var]} »</xmp>";
$MYREQUEST[$var] = $_REQUEST[$var] = NULL;
}
}
// check parameter semantics
if (empty($MYREQUEST['S_KEY']))
$MYREQUEST['S_KEY'] = "H";
if (empty($MYREQUEST['SORT']))
$MYREQUEST['SORT'] = "D";
if (empty($MYREQUEST['OB']))
$MYREQUEST['OB'] = OB_HOST_STATS;
if (!isset($MYREQUEST['COUNT']))
$MYREQUEST['COUNT'] = 20;
if (!isset($MYREQUEST['EXTRA']))
$MYREQUEST['EXTRA'] = '';
if (!isset($MYREQUEST['ZOOM']))
$MYREQUEST['ZOOM'] = 'TEXTECOURT';
if (!isset($MYREQUEST['TYPELISTE']))
$MYREQUEST['TYPELISTE'] = 'caches';
$MYREQUEST['SEARCH'] = trim ($MYREQUEST['SEARCH']);
global $MY_SELF; // fix apcu
global $MY_SELF_WO_SORT; // fix apcu
$MY_SELF_WO_SORT = "$PHP_SELF" . "?COUNT=" . $MYREQUEST['COUNT'] . "&SEARCH=" . $MYREQUEST['SEARCH'] . "&TYPECACHE=" . $MYREQUEST['TYPECACHE'] . "&ZOOM=" . $MYREQUEST['ZOOM'] . "&EXTRA=" . $MYREQUEST['EXTRA'] . "&WHERE=" . $MYREQUEST['WHERE'] . "&exec=" . $MYREQUEST['exec'] . "&OB=" . $MYREQUEST['OB']. "&TYPELISTE=" . $MYREQUEST['TYPELISTE'];
$MY_SELF = $MY_SELF_WO_SORT . "&S_KEY=" . $MYREQUEST['S_KEY'] . "&SORT=" . $MYREQUEST['SORT'];
global $self_pour_lien;
$self_pour_lien =
"http" . (!empty($_SERVER['HTTPS']) ? "s" : "") . "://"
. $_SERVER['SERVER_NAME']
// parametre_url fait un urlencode bienvenu pour les regexp qui peuvent contenir des ?
. parametre_url($_SERVER['REQUEST_URI'], 'SEARCH', $_REQUEST['SEARCH'] ?? '');
global $IMG_BASE;
$IMG_BASE = "$PHP_SELF" . "?exec=" . $MYREQUEST['exec'];
// clear APC cache
if (isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
apcu_clear_cache();
}
// clear APC & SPIP cache
if (isset($MYREQUEST['PP']) && $MYREQUEST['PP']) {
include_spip('inc/invalideur');
purger_repertoire(_DIR_SKELS);
apcu_clear_cache();
ecrire_meta('cache_mark', time());
xray_detecte_vidage ('Purge Xray // Bouton "Purger SPIP" ');
}
if (!empty($MYREQUEST['DU'])) {
apcu_delete($MYREQUEST['DU']);
}
if (!function_exists('apcu_cache_info')) {
echo "No cache info available. APC does not appear to be running.";
exit;
}
$cache = apcu_cache_info();
$mem = apcu_sma_info();
// don't cache this page
//
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache"); // HTTP/1.0
function duration($ts)
{
global $time;
$years = (int) ((($time - $ts) / (7 * 86400)) / 52.177457);
$rem = (int) (($time - $ts) - ($years * 52.177457 * 7 * 86400));
$weeks = (int) (($rem) / (7 * 86400));
$days = (int) (($rem) / 86400) - $weeks * 7;
$hours = (int) (($rem) / 3600) - $days * 24 - $weeks * 7 * 24;
$mins = (int) (($rem) / 60) - $hours * 60 - $days * 24 * 60 - $weeks * 7 * 24 * 60;
$str = '';
if ($years == 1)
$str .= "$years year, ";
if ($years > 1)
$str .= "$years years, ";
if ($weeks == 1)
$str .= "$weeks week, ";
if ($weeks > 1)
$str .= "$weeks weeks, ";
if ($days == 1)
$str .= "$days day,";
if ($days > 1)
$str .= "$days days,";
if ($hours == 1)
$str .= " $hours hour and";
if ($hours > 1)
$str .= " $hours hours and";
if ($mins == 1)
$str .= " 1 minute";
else
$str .= " $mins minutes";
return $str;
}
// create graphics
//
function graphics_avail()
{
return extension_loaded('gd');
}
if (isset($MYREQUEST['IMG'])) {
if (!graphics_avail()) {
exit(0);
}
function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1, $color2, $text = '', $placeindex = 0)
{
$r = $diameter / 2;
$w = deg2rad((360 + $start + ($end - $start) / 2) % 360);
if (function_exists("imagefilledarc")) {
// exists only if GD 2.0.1 is avaliable
imagefilledarc($im, $centerX + 1, $centerY + 1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL | IMG_ARC_EDGED);
} else {
imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start + 1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end - 1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
imagefill($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $color2);
}
if ($text) {
if ($placeindex > 0) {
imageline($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $diameter, $placeindex * 12, $color1);
imagestring($im, 4, $diameter, $placeindex * 12, $text, $color1);
} else {
imagestring($im, 4, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $text, $color1);
}
}
}
function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1, $text, $placeindex = 0)
{
$r = $diameter / 2;
$w = deg2rad((360 + $start + ($end - $start) / 2) % 360);
if ($placeindex > 0) {
imageline($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $diameter, $placeindex * 12, $color1);
imagestring($im, 4, $diameter, $placeindex * 12, $text, $color1);
} else {
imagestring($im, 4, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $text, $color1);
}
}
function fill_box($im, $x, $y, $w, $h, $color1, $color2, $text = '', $placeindex = '')
{
global $col_black;
$x1 = $x + $w - 1;
$y1 = $y + $h - 1;
imagerectangle($im, $x, $y1, $x1 + 1, $y + 1, $col_black);
if ($y1 > $y)
imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
else
imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
imagerectangle($im, $x, $y1, $x1, $y, $color1);
if ($text) {
if ($placeindex > 0) {
if ($placeindex < 16) {
$px = 5;
$py = $placeindex * 12 + 6;
imagefilledrectangle($im, $px + 90, $py + 3, $px + 90 - 4, $py - 3, $color2);
imageline($im, $x, $y + $h / 2, $px + 90, $py, $color2);
imagestring($im, 2, $px, $py - 6, $text, $color1);
} else {
if ($placeindex < 31) {
$px = $x + 40 * 2;
$py = ($placeindex - 15) * 12 + 6;
} else {
$px = $x + 40 * 2 + 100 * intval(($placeindex - 15) / 15);
$py = ($placeindex % 15) * 12 + 6;
}
imagefilledrectangle($im, $px, $py + 3, $px - 4, $py - 3, $color2);
imageline($im, $x + $w, $y + $h / 2, $px, $py, $color2);
imagestring($im, 2, $px + 2, $py - 6, $text, $color1);
}
} else {
imagestring($im, 4, $x + 5, $y1 - 16, $text, $color1);
}
}
}
$size = GRAPH_SIZE / 3; // image size
if ($MYREQUEST['IMG'] == 3)
$image = imagecreate(3 * $size + 200, 2 * $size + 150);
else
$image = imagecreate($size + 50, $size + 10);
$col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
$col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
$col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
$col_black = imagecolorallocate($image, 0, 0, 0);
imagecolortransparent($image, $col_white);
switch ($MYREQUEST['IMG']) {
case 1:
$s = $mem['num_seg'] * $mem['seg_size'];
$a = $mem['avail_mem'];
$x = $y = $size / 2;
$fuzz = 0.000001;
// This block of code creates the pie chart. It is a lot more complex than you
// would expect because we try to visualize any memory fragmentation as well.
$angle_from = 0;
$string_placement = array();
for ((int) $i = 0; $i < $mem['num_seg']; $i++) {
$ptr = 0;
$free = $mem['block_lists'][$i];
uasort($free, 'block_sort');
foreach ($free as $block) {
if ($block['offset'] != $ptr) { // Used block
$angle_to = $angle_from + ($block['offset'] - $ptr) / $s;
if (($angle_to + $fuzz) > 1)
$angle_to = 1;
if (($angle_to * 360) - ($angle_from * 360) >= 1) {
fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_red);
if (($angle_to - $angle_from) > 0.05) {
array_push($string_placement, array(
$angle_from,
$angle_to
));
}
}
$angle_from = $angle_to;
}
$angle_to = $angle_from + ($block['size']) / $s;
if (($angle_to + $fuzz) > 1)
$angle_to = 1;
if (($angle_to * 360) - ($angle_from * 360) >= 1) {
fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_green);
if (($angle_to - $angle_from) > 0.05) {
array_push($string_placement, array(
$angle_from,
$angle_to
));
}
}
$angle_from = $angle_to;
$ptr = $block['offset'] + $block['size'];
}
if ($ptr < $mem['seg_size']) { // memory at the end
$angle_to = $angle_from + ($mem['seg_size'] - $ptr) / $s;
if (($angle_to + $fuzz) > 1)
$angle_to = 1;
fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_red);
if (($angle_to - $angle_from) > 0.05) {
array_push($string_placement, array(
$angle_from,
$angle_to
));
}
}
}
foreach ($string_placement as $angle) {
text_arc($image, $x, $y, $size, $angle[0] * 360, $angle[1] * 360, $col_black, bsize($s * ($angle[1] - $angle[0])));
}
break;
case 2:
$s = $cache['num_hits'] + $cache['num_misses'];
$a = $cache['num_hits'];
fill_box($image, 30, $size, 50, $s ? (-$a * ($size - 21) / $s) : 0, $col_black, $col_green, sprintf("%.1f%%", $s ? $cache['num_hits'] * 100 / $s : 0));
fill_box($image, 130, $size, 50, $s ? -max(4, ($s - $a) * ($size - 21) / $s) : 0, $col_black, $col_red, sprintf("%.1f%%", $s ? $cache['num_misses'] * 100 / $s : 0));
break;
case 3:
$s = $mem['num_seg'] * $mem['seg_size'];
$a = $mem['avail_mem'];
$x = 130;
$y = 1;
$j = 1;
// This block of code creates the bar chart. It is a lot more complex than you
// would expect because we try to visualize any memory fragmentation as well.
for ($i = 0; $i < $mem['num_seg']; $i++) {
$ptr = 0;
$free = $mem['block_lists'][$i];
uasort($free, 'block_sort');
foreach ($free as $block) {
if ($block['offset'] != $ptr) { // Used block
$h = (GRAPH_SIZE - 5) * ($block['offset'] - $ptr) / $s;
if ($h > 0) {
$j++;
if ($j < 75)
fill_box($image, $x, $y, 50, $h, $col_black, $col_red, bsize($block['offset'] - $ptr), $j);
else
fill_box($image, $x, $y, 50, $h, $col_black, $col_red);
}
$y += $h;
}
$h = (GRAPH_SIZE - 5) * ($block['size']) / $s;
if ($h > 0) {
$j++;
if ($j < 75)
fill_box($image, $x, $y, 50, $h, $col_black, $col_green, bsize($block['size']), $j);
else
fill_box($image, $x, $y, 50, $h, $col_black, $col_green);
}
$y += $h;
$ptr = $block['offset'] + $block['size'];
}
if ($ptr < $mem['seg_size']) { // memory at the end
$h = (GRAPH_SIZE - 5) * ($mem['seg_size'] - $ptr) / $s;
if ($h > 0) {
fill_box($image, $x, $y, 50, $h, $col_black, $col_red, bsize($mem['seg_size'] - $ptr), $j++);
}
}
}
break;
case 4:
$s = $cache['num_hits'] + $cache['num_misses'];
$a = $cache['num_hits'];
fill_box($image, 30, $size, 50, $s ? -$a * ($size - 21) / $s : 0, $col_black, $col_green, sprintf("%.1f%%", $s ? $cache['num_hits'] * 100 / $s : 0));
fill_box($image, 130, $size, 50, $s ? -max(4, ($s - $a) * ($size - 21) / $s) : 0, $col_black, $col_red, sprintf("%.1f%%", $s ? $cache['num_misses'] * 100 / $s : 0));
break;
}
header("Content-type: image/png");
imagepng($image);
exit;
}
// pretty printer for byte values
//
function bsize($s)
{
foreach (array(
'',
'K',
'M',
'G'
) as $i => $k) {
if ($s < 1024)
break;
$s /= 1024;
}
return sprintf("%5.1f %sBytes", $s, $k);
}
// sortable table header in "scripts for this host" view
function sortheader($key, $name, $extra = '')
{
global $MYREQUEST;
// fix apcu l'affichage des headers ne doit pas changer $MYREQUEST
$sort = $MYREQUEST['SORT'];
if (!$sort)
$sort = 'D';
if ($MYREQUEST['S_KEY'] == $key)
$sort = (($sort == 'A') ? 'D' : 'A');
// global $MY_SELF_WO_SORT; // fix apcu : il faut global ici aussi
// $url = "$MY_SELF_WO_SORT$extra&S_KEY=$key&SORT=$SORT";
global $MY_SELF;
$url = parametre_url(parametre_url($MY_SELF.$extra,'S_KEY',$key),'SORT', $sort);
return "<a class=sortable href='$url'>$name</a>";
}
// create menu entry
function menu_entry($ob, $title)
{
global $MYREQUEST;
global $MY_SELF; // fix apcu
if ($MYREQUEST['OB'] != $ob) {
return "<li><a href='" . parametre_url($MY_SELF, 'OB', $ob) . "'>$title</a></li>";
} else if (empty($MYREQUEST['SH'])) {
return "<li><span class=active>$title</span></li>";
} else {
return "<li><a class=\"child_active\" href='$MY_SELF'>$title</a></li>";
}
}
function block_sort($array1, $array2)
{
if ($array1['offset'] > $array2['offset']) {
return 1;
} else {
return -1;
}
}
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>XRay - APCu Infos sur les caches SPIP et les squelettes utilisés ☠</title>
<style><!--
body { background:white; font-size:100.01%; margin:0; padding:0; }
body,p,td,th,input { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
* html body {font-size:0.8em}
* html p {font-size:0.8em}
* html td {font-size:0.8em}
* html th {font-size:0.8em}
* html input {font-size:0.8em}
td { vertical-align:top }
a { color:black; text-decoration:none; }
a:hover { text-decoration:underline; }
div.content { padding:1em 1em 1em 1em; width:97%; z-index:100; position: relative;}
h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
* html h1.apc { margin-bottom:-7px; }
h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
h1.apc div.logo {display: inline}
h1.apc div.logo span.logo {
background:rgb(119,123,180);
color:black;
border-right: solid black 1px;
border-bottom: solid black 1px;
font-style:italic;
font-size:1em;
padding-left:1.2em;
padding-right:1.2em;
text-align:right;
}
h1.apc div.nameinfo { color:white; display:inline; font-size:0.6em; margin-left: 1em; }
h1.apc div.nameinfo a { color:white; margin-left: 3em; }
h1.apc div.nameinfo img {margin-bottom: -10px; margin-right : 1em;}
hr.apc { display: none; }
ol,menu { padding:0.2em; margin: 1em 0 0 1em; }
ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
ol.menu a {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:white;
font-weight:bold;
margin-right:0;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
margin-left: 5px;
}
ol.menu span.active {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:black;
font-weight:bold;
margin-right:0;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
border-left: solid black 5px;
}
ol.menu span.inactive {
background:rgb(193,193,244);
border:solid rgb(182,182,233) 2px;
color:white;
font-weight:bold;
margin-right:0;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
margin-left: 5px;
}
ol.menu a:hover {
background:rgb(193,193,244);
text-decoration:none;
}
div.info {
background:rgb(204,204,204);
border:solid rgb(204,204,204) 1px;
margin-bottom:1em;
}
div.info h2 {
background:rgb(204,204,204);
color:black;
font-size:1em;
margin:0;
padding:0.1em 1em 0.1em 1em;
}
div.info table {
border:solid rgb(204,204,204) 1px;
border-spacing:0;
width:100%;
}
div.info table th {
background:rgb(204,204,204);
color:black;
margin:0;
padding:0.1em 1em 0.1em 1em;
}
div.info table th a.sortable { color:black; }
div.info table tr.tr-0 { background:rgb(238,238,238); }
div.info table tr.tr-1 { background:rgb(221,221,221); }
div.info table td { padding:0.3em 1em 0.3em 1em; }
div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; max-width: 666px; word-break:break-all; }
div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
div.info table td h3 {
color:black;
font-size:1.1em;
margin-left:-0.3em;
}
div.graph { margin-bottom:1em }
div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
div.graph table td.td-0 { background:rgb(238,238,238); }
div.graph table td.td-1 { background:rgb(221,221,221); }
div.graph table td { padding:0.2em 1em 0.4em 1em; }
div.div1,div.div2 { margin-bottom:1em; width:35em; }
div.div3 { position:absolute; left:40em; top:1em; width:580px; }
//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
div.sorting { margin:1.5em 0 1.5em 2em }
.center { text-align:center }
.aright { float: right; }
.right { text-align:right }
.ok { color:rgb(0,200,0); font-weight:bold}
.failed { color:rgb(200,0,0); font-weight:bold}
span.box {
border: black solid 1px;
border-right:solid black 2px;
border-bottom:solid black 2px;
padding:0 0.5em 0 0.5em;
margin-right:1em;
}
span.green { background:#60F060; padding:0 0.5em 0 0.5em}
span.red { background:#D06030; padding:0 0.5em 0 0.5em }
input {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:white;
font-weight:bold;
margin-right:1em;
padding:0.1em 0.5em 0.1em 0.5em;
}
/* xray styles */
xmp { display: inline }
.menuzoom {
border : 1px solid grey;
border-radius: 3px;
padding : 0 5px 0 5px;
}
td.td-0 .lien_suppl {
float: right;
font-size: 11px;
height: 11px
}
td.zoom {
word-wrap: break-word;
hyphens: auto;
max-width: 1px;
}
//-->
}
</style>
</head>
<body>
<div class="head">
<h1 class="apc">
<div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APCu">APCu</a></span></div>
<div class="nameinfo" style="display: inline">
Tout voir dans les caches
<a href='https://contrib.spip.net/4946'>
<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAEwAAABMBDsgnAwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAARiSURBVFiFxVdNSBtbFP5m8pqpRmw2EhAU/6JtQAStG5VEiC5cCkLBhcQuXIi2i0ppSZ+laGmxghJFwU1cZCe6cFFXKlYENybSQqMENa1SGLUEQ6iZ5CXfW/S9YEwm0YLtgUuY852f7557z5mJIAjCmSiKIgABPyXplyTS6a9rp4YLABLInxDxtyQRRQwMDKCioiItzpteDoeDiqKwpKQkHY74TSavra0lSb569UrNJjMBm83Guro6VVyj0fDt27fUarVp8cnJSX779o2SJKXF/8p0dgCg0+mwtLSEhoYGaLVa1NXVQa/Xw+12w+Px4N27d+jo6MCLFy/S+peXl2NzcxOKoqjmyFiBwsJCqkksFiNJjo2Nqfp//vyZQ0NDqrgoCAIySWtrKwDgx48fF3sZABAOhwEA9+/fV/XPz89HQUGBKp61De/duwcAePjwISorK7G7uwtFUdDU1ASLxQIAKC0tVfX3+Xyq7QcAEAQh4xHcvXuXiqLw69evXFtb4/n5OePxOBcXF/np0yeS5JMnT1T9p6eneXBwoN4p2QgA4PDwsOo9WF9fpyiKqr6PHj1iLBbj7du3VQnELipycnJSjCRJYktLC3t6eri/v0+SHB8fp81mY2FhYYr9xRj19fUkSYvFkp2ATqej3+9nW1sbATA/P58GgyFpbWxskCStVmsKJggCAdDr9bKrq+vnLRdFBgIBvnz5MjsBg8FAknz8+DGLiop4dnamWvp08vz5cwIgSb558yaRZGFhgaurq9cbRIeHh+ju7kZ9fX2SvrOzE8XFxXA6nZBlOaEPBAJwOp1pYy0vL2N0dBSSJKUOJFEU01YAAO12+5V3v7e3lxjHlytQVVVFkjSbzdcbxVNTUzg6OkJZWRm0Wq1qBQ4PD+F2uxGJRNLG2d3dxdHREZqbm/Hhw4erVwAArVZr1t3Pz88n7epyBQBwdnaWKysrmSsQDAaxvb0Nj8eT0K2srKC9vR2SJAEABgcHYTKZ8OzZM/j9fgDA5uZmyo53dnaSdMvLy5iZmUm9B6Io/nORUaahAoCrq6skyZqaGlWbvLy8FJ3JZCJJlpeXJ2OXCVxeBoOB79+/pyzL/P79O6PRKEkyGAwyEAjw4OCAnZ2dGUkDYFNTE0mmDq5sBPr6+rLegY8fP1Kv17O3t5d37txJG+fBgweMRCLMzc29HgGj0UhZllWTx+Nx9vf3U6fTcW9vjycnJ+zv7+etW7cSMfR6Pb1eLxcXF1NzaDSajAT+vxfhcJgTExOJsVtdXU2S7OvrS3pnPH36lMFgkF++fKHD4eDr16/p8Xjo9/tpNBpTY+MKEo/HQRKhUAiyLEOWZRwfHwMAotFowk5RFIyMjMBoNMLlcqG6uhpmsxlbW1tobGyEz+dLiZ31m/BXRJZl2O32K9n+lj8mmUQjiuLfZPajCIfDmJubw+npKYCf34iCIMDlciEUCv0yAUGj0URjsdiNHMVV5I8fgQDgHID03/PFFvktz/8C/6xwoasnBYAAAAAASUVORK5CYII=' >
XRay pour SPIP
</a>
</div>
</h1>
<hr class="apc">
</div>
<?php
// Les dossiers de squelettes déclarés dans le paquet.xml comme 'public' ne sont pas accessibles dans le privé
// Pour bénéficier des liens ici, il faut les ajouter dans la $GLOBALS['dossier_squelettes']
// echo "<h2>GLOBALS['dossier_squelettes'] : <pre>". print_r($GLOBALS['dossier_squelettes'],1)."</pre></h2>";
// echo "<h2>_chemin</h2> <pre>".print_r(_chemin(),1)."</p>";
?>
<?php
if ((($_GET['OB'] ?? 1)==1) and (!defined('_CACHE_KEY') or _CACHE_KEY)) {
echo "<div style='padding: 1em; background-color: lightpink;'>
<b title='la constante _CACHE_KEY est définie et non vide'>Le cache est crypté</b>. XRay ne fonctionne qu'à moitié avec des caches cryptés.<br>
Ajoutez <code>define('_CACHE_KEY', '');</code> dans votre mes_options.php (puis videz le cache pour le regénérer) le temps de l'analyse de votre site.</div>";
}
// Display main Menu
echo <<<EOB
<ol class=menu>
<li><a href="$MY_SELF&SH={$MYREQUEST['SH']}">Refresh</a></li>
EOB;
echo menu_entry(OB_HOST_STATS, 'Stats et infos'), menu_entry(OB_USER_CACHE, ' &#x1F9B4; &nbsp; XRay &nbsp; &#x1F9B4;');
if (test_plugin_actif('cachelab')) {
echo menu_entry (OB_CACHELAB, 'Tester CacheLab');
}
echo <<<EOB
<li><a class="aright" href="$MY_SELF&CC=1" onClick="javascript:return confirm('Are you sure?');"
title="Vider le cache APC user">Vider APC</a>
</li>
<li><a class="aright" href="$MY_SELF&PP=1"
onClick="javascript:return confirm('Êtes-vous certain de vouloir vider le cache APC user et le dossier skel/ des squelettes compilés ?');"
title="Vider le cache APC user ET effacer les caches de compilation des squelettes ?">
Purger SPIP</a>
</li>
</ol>
EOB;
if (isset($MYREQUEST['SOURCE']) and $MYREQUEST['SOURCE']) {
if (isset($_GET['action_link'])
and ($_GET['action_link']=='del_file')
){
$sf = supprimer_fichier ($s = $_GET['SOURCE']);
switch ($sf) {
case 'true' :
echo "<p style='color: green; margin:1em;'><b>Le fichier $s a bien été supprimé (ou alors il n'existait pas).</b></p>";
break;
case 'false' :
echo "<p style='color:red; margin:1em;'><b>Impossible de poser le vérou pour supprimer le fichier $s : renseignez-vous car je peux pas vous aider là</b></p>";
break;
default :
echo "<p style='color:red; margin:1em;'>On a essayé de supprimer le fichier compilé $s mais je sais pas trop ce qui s'est passé</p>";
}
$MYREQUEST['SOURCE'] = $_GET['SOURCE'] = '';
}
else {
if (file_exists ($MYREQUEST['SOURCE'])) {
echo "<h1>{$MYREQUEST['SOURCE']}</h1>
<xmp>" . file_get_contents ($MYREQUEST['SOURCE']) . '</xmp>';
} else {
echo "<b style='color: red'>Erreur : Le fichier {$MYREQUEST['SOURCE']} n'existe pas</b>";
}
exit;
}
}
// CONTENT
echo <<<EOB
<div class="content">
EOB;
$Memoization = memoization();
switch ($MYREQUEST['OB']) {
// -----------------------------------------------
// Host Stats
// -----------------------------------------------
case OB_HOST_STATS:
$mem_size = $mem['num_seg'] * $mem['seg_size'];
$mem_avail = $mem['avail_mem'];
$mem_used = $mem_size - $mem_avail;
$seg_size = bsize($mem['seg_size']);
$req_rate_user = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits'] + $cache['num_misses']) / max(1, $time - $cache['start_time'])) : 0);
$hit_rate_user = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits']) / max(1, $time - $cache['start_time'])) : 0);
$miss_rate_user = sprintf("%.2f", $cache['num_misses'] ? (($cache['num_misses']) / max(1, $time - $cache['start_time'])) : 0);
$insert_rate_user = sprintf("%.2f", $cache['num_inserts'] ? (($cache['num_inserts']) / max(1, $time - $cache['start_time'])) : 0);
$apcversion = phpversion('apcu');
$phpversion = phpversion();
$number_vars = $cache['num_entries'];
$size_vars = bsize($cache['mem_size']);
$i = 0;
$_namespace = _CACHE_NAMESPACE;
echo "<div class='info div1'><h2>Mémoization SPIP - Le ".date(JOLI_DATE_FORMAT,time())."</h2>
<table cellspacing=0><tbody>
<tr class=tr-0><td class=td-0>Config</td><td><pre>".trim(preg_replace('/(^Array\s*\(|^\s*|^\)$)/im', '', print_r(unserialize($GLOBALS['meta']['memoization']),1)))."</pre></td></tr>
<tr class=tr-0><td class=td-0>_CACHE_NAMESPACE</td><td>"._CACHE_NAMESPACE."</td></tr>
<tr class=tr-0><td class=td-0>_CACHE_KEY</td><td>"._CACHE_KEY."</td></tr>
<tr class=tr-0><td class=td-0 title='meta SPIP : derniere_modif'>Dernière invalidation</td><td>".date(JOLI_DATE_FORMAT, $meta_derniere_modif)."</td></tr>
<tr class=tr-0><td class=td-0 title='meta spip'>Invalidation de '".XRAY_OBJET_SPECIAL."'</td><td>".date(JOLI_DATE_FORMAT, lire_config('derniere_modif_'.XRAY_OBJET_SPECIAL))."</td></tr>";
if (isset($GLOBALS['meta']['cache_mark'])) {
echo "<tr class=tr-0><td class=td-0 title='meta SPIP : cache_mark'>Dernière purge</td><td>" . date (JOLI_DATE_FORMAT, $GLOBALS['meta']['cache_mark']) . "</td></tr>";
}
$detecte_vidage = $Memoization->get('xray_detecte_vidage');
echo "<tr class=tr-0>
<td class=td-0 title='Détecte aussi les vidages automatiquement provoqués par la saturation du cache'>Détection dernier vidage</td>
<td title='".trim(substr($detecte_vidage, strpos($detecte_vidage, '//')+2))."'>"
.rtrim(substr($detecte_vidage, 0, strpos($detecte_vidage, '//')))
."</td></tr>
";
$stats = xray_stats($cache);
echo xray_stats_print($stats, 'generaux', 'Valides '.XRAY_LABEL_STATS_SPECIALES_EXCLUES);
echo xray_stats_print($stats, 'speciaux', '+ Valides '.XRAY_LABEL_STATS_SPECIALES);
echo xray_stats_print($stats, 'invalides', '+ Invalidés par SPIP');
echo xray_stats_print($stats, 'existent', '= Total caches APC OK');
echo xray_stats_print($stats, 'fantomes', '+ Caches périmés par APC');
$nb_cache = count($cache['cache_list']);
echo "<tr class=tr-0>
<td class=td-0><b>= Nb total caches APC</b></td><td>$nb_cache</td>
</tr>";
echo "</table></div>";
echo <<< EOB
<div class="info div1"><h2>General Cache Information</h2>
<table cellspacing=0><tbody>
<tr class=tr-0><td class=td-0>APCu Version</td><td>$apcversion</td></tr>
<tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
EOB;
if (!empty($_SERVER['SERVER_NAME']))
echo "<tr class=tr-0><td class=td-0>APCu Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
if (!empty($_SERVER['SERVER_SOFTWARE']))
echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
echo <<<EOB
<tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
<br/> ({$cache['memory_type']} memory)
</td></tr>
EOB;
echo '<tr class=tr-1><td class=td-0>Start Time</td><td>', date(DATE_FORMAT, $cache['start_time']), '</td></tr>';
echo '<tr class=tr-0><td class=td-0>Uptime</td><td>', duration($cache['start_time']), '</td></tr>';
echo <<<EOB
</tbody></table>
</div>
<div class="info div1"><h2>Cache Information</h2>
<table cellspacing=0>
<tbody>
<tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
<tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
<tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
</tbody>
</table>
</div>
<div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
EOB;
$j = 0;
foreach (ini_get_all('apcu') as $k => $v) {
echo "<tr class=tr-$j><td class=td-0>", $k, "</td><td>", str_replace(',', ',<br />', $v['local_value']), "</td></tr>\n";
$j = 1 - $j;
}
if ($mem['num_seg'] > 1 || $mem['num_seg'] == 1 && count($mem['block_lists'][0]) > 1)
$mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
else
$mem_note = "Memory Usage";
echo <<< EOB
</tbody></table>
</div>
<div class="graph div3"><h2>Host Status Diagrams</h2>
<table cellspacing=0><tbody>
EOB;
$size = 'width=' . (GRAPH_SIZE * 2 / 3) . ' height=' . (GRAPH_SIZE / 2);
echo <<<EOB
<tr>
<td class=td-0>$mem_note</td>
<td class=td-1>Hits &amp; Misses</td>
</tr>
EOB;
$n = $cache['num_hits'] + $cache['num_misses'];
echo graphics_avail() ?
'<tr>'
. "<td class=td-0><img alt='' $size src='{$IMG_BASE}&IMG=1&$time'></td>"
. "<td class=td-1><img alt='' $size src='{$IMG_BASE}&IMG=2&$time'></td>
</tr>\n"
: "",
'<tr>',
'<td class=td-0><span class="green box">&nbsp;</span>Free: ',
bsize($mem_avail) . ($mem_size ? sprintf(" (%.1f%%)", $mem_avail * 100 / $mem_size) : ''),
"</td>\n",
'<td class=td-1><span class="green box">&nbsp;</span>
Hits: ', $cache['num_hits'] . ($n ? sprintf(" (%.1f%%)", $cache['num_hits']*100/$n) : ''),
"</td>\n",
'</tr>',
'<tr>',
'<td class=td-0><span class="red box">&nbsp;</span>
Used: ', bsize($mem_used) . ($mem_size ? sprintf(" (%.1f%%)", $mem_used * 100 / $mem_size) : ''),
"</td>\n",
'<td class=td-1><span class="red box">&nbsp;</span>
Misses: ', $cache['num_misses'] . ($n ? sprintf(" (%.1f%%)", $cache['num_misses']*100/$n):''),
"</td>
</tr>";
echo "</tr></tbody></table>
<br/>
<h2>Detailed Memory Usage and Fragmentation</h2>
<table cellspacing=0><tbody>
<tr>
<td class=td-0 colspan=2><br/>";
// Fragementation: (freeseg - 1) / total_seg
$nseg = $freeseg = $fragsize = $freetotal = 0;
for ($i = 0; $i < $mem['num_seg']; $i++) {
$ptr = 0;
foreach ($mem['block_lists'][$i] as $block) {
if ($block['offset'] != $ptr) {
++$nseg;
}
$ptr = $block['offset'] + $block['size'];
/* Only consider blocks <5M for the fragmentation % */
if ($block['size'] < (5 * 1024 * 1024))
$fragsize += $block['size'];
$freetotal += $block['size'];
}
$freeseg += count($mem['block_lists'][$i]);
}
if ($freeseg > 1) {
$frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize / $freetotal) * 100, bsize($fragsize), bsize($freetotal), $freeseg);
} else {
$frag = "0%";
}
if (graphics_avail()) {
$size = 'width=' . (2 * GRAPH_SIZE + 150) . ' height=' . (GRAPH_SIZE + 10);
echo <<<EOB
<img alt="" $size src="{$IMG_BASE}&IMG=3&$time">
EOB;
}
echo <<<EOB
</br>Fragmentation: $frag
</td>
</tr>
EOB;
if (isset($mem['adist'])) {
foreach ($mem['adist'] as $i => $v) {
$cur = pow(2, $i);
$nxt = pow(2, $i + 1) - 1;
if ($i == 0)
$range = "1";
else
$range = "$cur - $nxt";
echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
}
}
echo <<<EOB
</tbody></table>
</div>
EOB;
break;
// -----------------------------------------------
// User Cache Entries
// -----------------------------------------------
case OB_USER_CACHE:
$cols = 7;
echo xray_menu_scanner();
// Préparation de l'expression recherchée pour les filtres qui suivront
$MYREQUEST['SEARCH'] = xray_prepare_search($MYREQUEST['SEARCH'] ?? '', $MYREQUEST['WHERE'] ?? '');
echo xray_scanner_head($MYREQUEST['TYPELISTE']);
$cache = xray_sort_caches ($cache, $MYREQUEST['S_KEY'], $MYREQUEST['SORT']);
if (!$cache) {
// En l'absence de tout cache
echo '<tr class=tr-0><td class="center" colspan=', $cols, '><i>No data</i></td></tr>';
}
// Préparation du filtrage par type de caches
$pattern_typecache = $also_required = '';
$also_required_bool = true;
xray_prepare_filtrage(
isset($MYREQUEST['TYPECACHE']) ? $MYREQUEST['TYPECACHE'] : 'ALL',
$pattern_typecache,
$also_required,
$also_required_bool
);
$liste_squelettes = array();
$i_list = $size_list = $totalcount_list = 0;
$descriptif = '';
foreach ($cache as $k => $entry) {
// on économise pas (plus maintenant) la lecture du contenu du cache, qui augmente donc le nbhits lu
$data_success = false;
$data = get_apc_data($entry['info'], $data_success);
$search = $MYREQUEST['SEARCH'] ?? '';
$searched = xray_get_searched_part ($data, $search, $MYREQUEST['WHERE'] ?? '');
$found = [];
if (
(!isset($pattern_typecache)
or !$pattern_typecache
or preg_match($pattern_typecache, $entry['info'])
)
and (!$search
or (!$MYREQUEST['WHERE']
and preg_match($search, $entry['info'], $found))
or ($MYREQUEST['WHERE']
and preg_match($search.'m', print_r($searched,1), $found)))
and (!$also_required
or ($also_required($entry['info'], $data) == $also_required_bool))
) {
$descriptif = "%s caches listés";
if (isset($_REQUEST['DelSubmit']) and ($_REQUEST['DelSubmit']=='X')) {
$mkey = xray_cachekey_to_memoizationkey($entry['info']);
$destroyed = $Memoization->del($mkey);
// cachelab_cibler n'est pas prévu pour les caches non SPIP
// $destroyed = cachelab_cibler('del', ['chemin'=>$entry['info']], ['clean'=>false]);
// if (!$destroyed or !$destroyed['nb_cible']) {
if (!$destroyed) {
echo "<b style='color:red'>PB : {$entry['info']} n'a pas été effacé (mkey = $mkey)</b><br>";
}
else {
$i_list++;
}
$descriptif = "%s caches effacés sur un total de %s caches";
$totalcount_list++;
continue;
}
elseif ($MYREQUEST['TYPELISTE']=='squelettes') {
// Pour la liste des squelettes, on agrège les infos des caches correspondants, sans rien afficher pour l'instant
$descriptif = "%s squelettes listés sur un total de %s squelettes";
$joli = array();
if (!is_array($data)) { // textwheel etc
continue;
}
if (isset($data['source'])) {
$source = $data['source'];
}
else {
// talons (sans 'source')
// Le radical (peu d'intérêt) est relatif aux CHEMINs SPIP
// Pour le lien il faut l'adresse systeme
$source = find_in_path ($r=cache_get_radical($entry['info']) . '.html');
if (!$source) {
$m_skelerror="Impossible de trouver le fichier squelette '$r' dans les chemins SPIP pour '".$entry['info']."'. Ça arrive pour certains squelettes de pages (squelettes principaux, non inclus)";
}
elseif (substr($source,0, 3)=== '../') {
$source = substr($source, 2);
}
else {
$m_skelerror="Pas de ../ en retour du find_in_path '$source' du radical '$r' pour '".$entry['info']."'";
}
if ($m_skelerror ?? '') {
$m_skelerror .= ". Le cache contient : <pre>".print_r($entry, 1).'</pre>';
spip_log ($m_skelerror, "ERREUR_xray");
echo "<span style='color:red'>ERREUR : $m_skelerror</span>";
}
}
$slug = slugify ($source);
/* il faut tout rassembler puis trier avant de limiter le nombre à $MYREQUEST['COUNT']) */
if (array_key_exists($slug, $liste_squelettes)) {
// déjà listé
$liste_squelettes[$slug]['nb']++;
if (!$liste_squelettes[$slug]['source']) {// au cas où
$liste_squelettes[$slug]['source'] = $source;
}
$liste_squelettes[$slug]['mem_size'] += $entry['mem_size'];
$liste_squelettes[$slug]['num_hits'] += $entry['num_hits'];
}
// squelette pas encore listé
else {
$i_list++;
$liste_squelettes[$slug] = [
'nb'=>1,
'source'=>$source,
'mem_size' => $entry['mem_size'],
'skel' => ($data['squelette'] ?? ''),
'num_hits' => $entry['num_hits']
];
}
if (isset ($liste_squelettes[$slug]) and !$liste_squelettes[$slug]['skel']) {
if ($liste_squelettes[$slug]['nb'] == 1) {
// Ça arrive pour des squelettes de pages (squelettes non inclus)
// après un ci-dessus « Impossible de trouver le fichier squelette 'rubrique/rubrique.html' dans les chemins SPIP pour 'prefixesite:cache:ebd79fe90961fe9565e703fa5785f808-rubrique/rubrique' »
spip_log ("Pas de skel enregistré pour le source " . print_r($liste_squelettes[$slug],1), "MYSTERE_xray");
}
elseif ($data['squelette'] ?? false) {
$liste_squelettes[$slug]['skel'] = $data['squelette'];
spip_log (
"Pas de skel enregistré pour le source " . $liste_squelettes[$slug]['source']
." MAIS là, pour le cache n°{$liste_squelettes[$slug]['nb']}, on a skel=" . $data['squelette'],
"MYSTERE_xray");
}
}
// Même aprés avoir le bon compte à afficher, on continue à scanner les caches
// pour avoir à la fin le bon nombre de caches pour chaque squelette listé
continue; // Fin de la préparation du cas "on liste les squelettes"
}
// Maintenant on liste les caches
$displayed_name_org = $displayed_name = htmlentities(strip_tags($entry['info'], ''), ENT_QUOTES, 'UTF-8');
$displayed_name = str_replace (_CACHE_NAMESPACE.'cache:', '', $displayed_name);
$displayed_name = str_replace (_CACHE_NAMESPACE, '<span title="Pas un cache squelette" style="color:orange">[NON SQUEL]</span> ', $displayed_name);
$xray_nepasafficher_autres_sites = ($_GET['xray_nepasafficher_autres_sites'] ?? XRAY_NEPASAFFICHER_AUTRES_SITES);
if ($xray_nepasafficher_autres_sites and ($displayed_name_org == $displayed_name)) {
continue;
}
$i_list++;
$size_list += $entry['mem_size'];
$sh = md5($entry["info"]);
if (!XRAY_NEPASAFFICHER_DEBUTNOMCACHE) {
$displayed_name = $displayed_name_org;
}
echo '<tr id="key-' . $sh . '" class=tr-', $i_list % 2, '>',
"<td class='td-0' style='position: relative'>
$i_list)
<a href='$MY_SELF&SH={$sh}#key-{$sh}'>
$displayed_name
</a>";
if ($data and cache_est_talon($entry['info'], $data)) {
echo "<span style='margin-left:2em' title='Talon des caches sessionnés avec ce squelette et le même contexte'>[talon]</span>";
}
if (!$data_success) {
echo '<span style="color:red">Cache invalide ou non SPIP : '.explique_echec ($entry['info']).'</span>';
}
$boutons_liens = '';
if ($p = preg_match(XRAY_PATTERN_SESSION_AUTH, $displayed_name, $match)
and $search != "~_{$match[1]}$~i") {
$url_session = parametre_url($MY_SELF, 'SEARCH', '_'.$match[1].'$');
$url_session = parametre_url($url_session, 'WHERE', '');
$boutons_liens .= bouton_session($match[1], $url_session);
}
if (is_array($data)
and isset($data['invalideurs']['session'])) {
$p = preg_match(XRAY_PATTERN_TALON, $displayed_name, $match);
$bouton_mm_talon='[mm talon]';
if ($p and $match[1] and ($search!=$match[1])) {
$url_mm_talon = parametre_url($MY_SELF, 'TYPECACHE', 'ALL');
$url_mm_talon = parametre_url($url_mm_talon, 'SEARCH', $match[1]);
$url_mm_talon = parametre_url($url_mm_talon, 'WHERE', '');
}
else
$bouton_mm_talon='(! Err get talon !)';
$boutons_liens .= "<a class='lien_suppl' href='$url_mm_talon' title='Caches du même squelette et avec le même contexte'>$bouton_mm_talon</a>";
}
echo '<span style="float: right">'.$boutons_liens.'</span>';
if (count($found) and $MYREQUEST['WHERE']) {
echo '<div class="found" style="color:rgb(119,123,180);">Trouvé <xmp>'.$search.'\' : '.($found[0]).'</xmp></div>';
}
if (
$MYREQUEST['EXTRA']
and ($sh != $MYREQUEST["SH"]) // sinon yaura un zoom après et c'est inutile de répéter ici
and $data_success
) {
echo '<br>'. prepare_extra($data, $MYREQUEST['EXTRA']) . '</br>';
} // fin affichage Extra
echo '</td>
<td class="td-n center">', $entry['num_hits'], '</td>
<td class="td-n right">', $entry['mem_size'], '</td>
<td class="td-n center">', date(DATE_FORMAT, $entry['creation_time']),
'</td>';
if ($entry['ttl']) {
$est_perime = cache_est_perime ($entry['info'], $entry);
echo '<td class="td-n center">' . $entry['ttl'] . ' seconds',
($est_perime ? '<br><span style="color:red">'.$est_perime.'</span>' : ''),
'</td>';
} else {
echo '<td class="td-n center">None</td>';
}
if ($MYREQUEST['OB'] == OB_USER_CACHE) {
echo '<td class="td-last center">';
echo '<a href="', $MY_SELF, '&DU=', urlencode($entry['info']), '" style="color:red">X</a>';
echo '</td>';
} else
echo '<td class="td-last center"> &nbsp; </td>';
echo '</tr>';
if ($sh == $MYREQUEST["SH"]) { // Le ZOOM sur une entrée
echo '<tr>';
echo '<td colspan="6" class="zoom">';
if (!isset($_GET['ZOOM']) or ($_GET['ZOOM'] != 'TEXTELONG')) {
$url = parametre_url($self_pour_lien, 'ZOOM', 'TEXTELONG') . "#key-$sh";
$menuzoom = "<a href='$url' class='menuzoom'>Voir tout le texte</a> ";
if (is_array($data) and isset($data['texte']))
$data['texte'] = ajuste_longueur_html($data['texte']);
} else {
$url = parametre_url($self_pour_lien, 'ZOOM', 'TEXTECOURT') . "#key-$sh";
$menuzoom = "<a href='$url' class='menuzoom'>Voir texte abbrégé</a> ";
}
$url = parametre_url($self_pour_lien, 'SH', '') . "#key-$sh";
$menuzoom .= "<a href='$url' class='menuzoom'>Replier</a>";
if ($data_success) {
echo "<p>$menuzoom</p>";
echo xray_joli_cache($data);
} else {
echo '! Échec ou pas un cache spip ( ' . explique_echec ($entry['info']) . ' )';
}
echo '</td>';
echo '</tr>';
} // fin du zoom SH
if ($i_list == $MYREQUEST['COUNT']) {
break;
}
} // fin du filtrage et de l'affichage lorsqu'on veut les caches
} // fin du foreach
// Si on liste les squelettes, on a récolté et compté mais encore rien trié ni affiché.
// Maintenant on peut trier et afficher.
if ($MYREQUEST['TYPELISTE']=='squelettes') {
$liste_squelettes = xray_sort_squelettes ($liste_squelettes, $MYREQUEST['S_KEY'], $MYREQUEST['SORT']);
$totalcount_list = count($liste_squelettes);
$i_list = 1;
foreach ($liste_squelettes as $slug => $s) {
// Les dossiers de squelettes déclarés comme public dans paquet.xml
// ne sont pas utilisés par find_in_path dans le privé
echo "<tr class='tr-".($i_list % 2)."'>
<td>$i_list) ";
$squel_caches = parametre_url($self_pour_lien, 'TYPELISTE', 'caches');
$squel_caches = parametre_url($squel_caches, 'WHERE', 'FICHIER_SOURCE');
if (!$s['source']) {
echo "Pour '$slug' : " .
' <span style="color:red" title="Parfois la forme du squelette n’est pas prévue par CacheLab, mais avez-vous déclaré le chemin de vos dossiers publics de squelettes dans GLOBALS[\'dossier_squelette\'] ?">
ÉCHEC accés au squelette (avec données du cache et avec find_in_path sur nom du cache)
</span>
<pre>'.$slug.' => '.print_r($s,1).'<pre>
</td><td>';
$squel_caches = parametre_url ($squel_caches, 'SEARCH', $slug);
}
else {
echo xray_link_to_file ('source', $s['source'], false)."</td><td>"
. xray_link_to_file ('squelette', $s['skel'], false);
$squel_caches = parametre_url ($squel_caches, 'SEARCH', $s['source']);
}
echo "</td>
<td><a href='$squel_caches'>[{$s['nb']} caches]</a></td>
<td>{$s['num_hits']}</td>
<td>".taille_en_octets ($s['mem_size'])."</td>
</tr>";
$i_list++;
if ($i_list >= $MYREQUEST['COUNT']) {
break;
}
}
}// fin si squelettes
echo "
</tbody></table>
</div>";
if ($descriptif) {
printf ("<p>$descriptif</p>", $i_list, $totalcount_list);
}
if ($size_list > 0) {
echo "<p>Taille totale des caches listés : $size_list octets, soit ".taille_en_octets ($size_list)."</p>";
}
break;
case OB_CACHELAB :
include_spip('inc/cachelab');
include('cachelab_diag.php');
break;
}
?>
</div>
<!--
Based on APCGUI By R.Becker\n$VERSION
-->
</body>
</html>