source: spip-zone/_plugins_/xray/trunk/xray_apc.php @ 107447

Last change on this file since 107447 was 107447, checked in by jluc@…, 2 years ago

si macrosession est actif, afficher le champ consulté pour chaque occurence de #_SESSION

File size: 51.9 KB
Line 
1<?php
2/*
3+----------------------------------------------------------------------+
4| APC                                                                  |
5+----------------------------------------------------------------------+
6| Copyright (c) 2006-2011 The PHP Group                                |
7+----------------------------------------------------------------------+
8| This source file is subject to version 3.01 of the PHP license,      |
9| that is bundled with this package in the file LICENSE, and is        |
10| available through the world-wide-web at the following url:           |
11| http://www.php.net/license/3_01.txt                                  |
12| If you did not receive a copy of the PHP license and are unable to   |
13| obtain it through the world-wide-web, please send a note to          |
14| license@php.net so we can mail you a copy immediately.               |
15+----------------------------------------------------------------------+
16| Authors: Ralf Becker <beckerr@php.net>                               |
17|          Rasmus Lerdorf <rasmus@php.net>                             |
18|          Ilia Alshanetsky <ilia@prohost.org>                         |
19|          JLuc http://contrib.spip.net/JLuc                           |
20+----------------------------------------------------------------------+
21
22All other licensing and usage conditions are those of the PHP Group.
23
24*/
25
26if (!autoriser('webmestre'))
27        die("Autorisation non accordée : devenez webmestre d'abord.");
28
29$VERSION = '$Id$';
30
31////////// READ OPTIONAL CONFIGURATION FILE ////////////
32if (file_exists("apc.conf.php"))
33        include("apc.conf.php");
34////////////////////////////////////////////////////////
35
36////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
37
38defaults('USE_AUTHENTICATION', 0); // Use (internal) authentication - best choice if
39// no other authentication is available
40// If set to 0:
41//  There will be no further authentication. You
42//  will have to handle this by yourself!
43// If set to 1:
44//  You need to change ADMIN_PASSWORD to make
45//  this work!
46defaults('ADMIN_USERNAME', 'admin'); // Admin Username
47defaults('ADMIN_PASSWORD', 'password'); // Admin Password - CHANGE THIS TO ENABLE!!!
48
49// (beckerr) I'm using a clear text password here, because I've no good idea how to let
50//           users generate a md5 or crypt password in a easy way to fill it in above
51
52// defaults('DATE_FORMAT', "d.m.Y H:i:s");      // German
53defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
54
55defaults('GRAPH_SIZE', 400); // Image size
56
57//defaults('PROXY', 'tcp://127.0.0.1:8080');
58
59// _CACHE_NAMESPACE est défini par memoization et préfixe chaque nom de cache SPIP
60// On ne souhaite pas que cette partie du nom s'affiche sur chaque ligne
61define('XRAY_NEPASAFFICHER_DEBUTNOMCACHE', _CACHE_NAMESPACE);
62
63////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
64
65// Strings utils
66
67function is_serialized($str)
68{
69        return ($str == serialize(false) || @unserialize($str) !== false);
70}
71function get_serial_class($serial)
72{
73        $types = array(
74                's' => 'string',
75                'a' => 'array',
76                'b' => 'bool',
77                'i' => 'int',
78                'd' => 'float',
79                'N;' => 'NULL'
80        );
81       
82        $parts = explode(':', $serial, 4);
83        return isset($types[$parts[0]]) ? $types[$parts[0]] : trim($parts[2], '"');
84}
85
86function get_apc_data($info, &$success) {
87        if (apcu_exists($info)
88                and ($data = apcu_fetch($info, $success)) 
89                and $success 
90                and is_array($data) and (count($data) == 1) 
91                and is_serialized($data[0]))
92                return unserialize($data[0]);
93        $success = false;
94        return null;
95}
96
97function spipsafe_unserialize($str)
98{
99        if (strpos($str, "SPIPTextWheelRuleset") !== false) {
100                if (isset($_GET['ZOOM']) and ($_GET['ZOOM'] == 'TEXTECOURT'))
101                        return "Début : " . substr(trim($str), 0, 80) . '...';
102                else
103                        return "Brut : $str";
104        }
105        $unser = unserialize($str);
106        if (is_array($unser) and isset($unser['texte']) and isset($_GET['ZOOM']) and ($_GET['ZOOM'] == 'TEXTECOURT')) {
107                $unser['texte'] = trim(preg_replace('/\s+/', ' ', $unser['texte']));
108                if (mb_strlen($unser['texte']) > 80)
109                        $unser['texte'] = mb_substr($unser['texte'], 0, 80) . '...';
110                elseif (!$unser['texte'])
111                        $unser['texte'] = '(vide)';
112        }
113        return print_contexte($unser, 1);
114}
115
116function print_contexte($extra, $tostring)
117{
118        $print = print_r($extra, 1);
119        if (stripos($print, 'Array') === 0) {
120                // On enlève 'Array( ' au début et ')' à la fin
121                $print = trim(substr($print, 5), " (\n\r\t");
122                $print = substr ($print, 0, -1);
123                $print = preg_replace_callback("/\[id_([a-z\-_]+)\]\s*=>\s*(\d+)$/im", function($match) use ($extra)
124                {
125                        return $match[0] . '</xmp>' . bouton_objet($match[1], $match[2], $extra) . '<xmp>';
126                }, $print);
127        }
128        $print=preg_replace('/^    /m', '', $print);
129        if ($tostring)
130                return $print;
131        echo $print;
132}
133
134function bouton_objet($objet, $id_objet, $extra)
135{
136        $objet_visible = $objet;
137        if ($objet == 'secteur')
138                $objet = 'rubrique';
139        elseif (($objet == 'objet')     and isset ($extra['objet']))
140        {
141                $objet_visible = $objet = $extra['objet'];
142        };
143        return "<a href='/ecrire/?exec=$objet&id_$objet=$id_objet' target='blank'
144                        style='position:absolute; right:1em'
145                        title=\"" . attribut_html(generer_info_entite($id_objet, $objet, 'titre', 'etoile')) . "\">[voir $objet_visible]</a>";
146}
147
148if (!function_exists('plugin_est_actif')) {
149        function plugin_est_actif($prefixe) {
150                $f = chercher_filtre('info_plugin');
151                return $f($prefixe, 'est_actif');
152        }
153}
154
155////////////////////////////////////////////////////////////////////////
156
157// "define if not defined"
158function defaults($d, $v)
159{
160        if (!defined($d))
161                define($d, $v); // or just @define(...)
162}
163
164// rewrite $PHP_SELF to block XSS attacks
165//
166$PHP_SELF = isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'], ''), ENT_QUOTES, 'UTF-8') : '';
167$time     = time();
168$host     = php_uname('n');
169if ($host) {
170        $host = '(' . $host . ')';
171}
172if (isset($_SERVER['SERVER_ADDR'])) {
173        $host .= ' (' . $_SERVER['SERVER_ADDR'] . ')';
174}
175
176// operation constants
177define('OB_HOST_STATS', 1);
178define('OB_USER_CACHE', 2);
179define('OB_VERSION_CHECK', 3);
180
181// check validity of input variables
182$vardom = array(
183        'exec' => '/^[a-zA-Z_\-0-9]+$/', // pour #URL_ECRIRE{xray}
184        'OB' => '/^\d+$/', // operational mode switch
185        'CC' => '/^[01]$/', // clear cache requested
186        'DU' => '/^.*$/', // Delete User Key
187        'SH' => '/^[a-z0-9]*$/', // shared object description
188       
189        'IMG' => '/^[123]$/', // image to generate
190        'LO' => '/^1$/', // login requested
191       
192        'COUNT' => '/^\d+$/', // number of line displayed in list
193        'SCOPE' => '/^[AD]$/', // list view scope
194        'S_KEY' => '/^[AHSMCDTZ]$/', // first sort key
195        'SORT' => '/^[DA]$/', // second sort key
196        'AGGR' => '/^\d+$/', // aggregation by dir level
197        'SEARCH' => '~.*~',
198        'TYPECACHE' => '/^(|ALL|SESSIONS|SESSIONS_AUTH|SESSIONS_NONAUTH|FORMULAIRES)$/', //
199        'ZOOM' => '/^(|TEXTECOURT|TEXTELONG)$/', //
200        'WHERE' => '/^(|ALL|HTML|META)$/', // recherche dans le contenu
201        'EXTRA' => '/^(|CONTEXTE|CONTEXTES_SPECIAUX|INFO_AUTEUR|INVALIDEURS|INVALIDEURS_SPECIAUX|INCLUSIONS'
202                .(plugin_est_actif('macrosession') ? '|MACROSESSIONS' : '')
203                .')$/'          // Affichage pour chaque élément de la liste
204);
205
206// cache scope
207$scope_list = array(
208        'A' => 'cache_list',
209        'D' => 'deleted_list'
210);
211
212global $MYREQUEST; // fix apcu
213// handle POST and GET requests
214if (empty($_REQUEST)) {
215        if (!empty($_GET) && !empty($_POST)) {
216                $_REQUEST = array_merge($_GET, $_POST);
217        } else if (!empty($_GET)) {
218                $_REQUEST = $_GET;
219        } else if (!empty($_POST)) {
220                $_REQUEST = $_POST;
221        } else {
222                $_REQUEST = array();
223        }
224}
225
226// check parameter syntax
227foreach ($vardom as $var => $dom) {
228        if (!isset($_REQUEST[$var]))
229                $MYREQUEST[$var] = NULL;
230        else if (!is_array($_REQUEST[$var]) && preg_match($dom . 'D', $_REQUEST[$var]))
231                $MYREQUEST[$var] = $_REQUEST[$var];
232        else {
233                echo "<xmp>ERREUR avec parametre d'url « $var » qui vaut « {$_REQUEST[$var]} »</xmp>";
234                $MYREQUEST[$var] = $_REQUEST[$var] = NULL;
235        }
236}
237
238// check parameter sematics
239if (empty($MYREQUEST['SCOPE']))
240        $MYREQUEST['SCOPE'] = "A";
241if (empty($MYREQUEST['S_KEY']))
242        $MYREQUEST['S_KEY'] = "H";
243if (empty($MYREQUEST['SORT']))
244        $MYREQUEST['SORT'] = "D";
245if (empty($MYREQUEST['OB']))
246        $MYREQUEST['OB'] = OB_HOST_STATS;
247if (!isset($MYREQUEST['COUNT']))
248        $MYREQUEST['COUNT'] = 20;
249if (!isset($scope_list[$MYREQUEST['SCOPE']]))
250        $MYREQUEST['SCOPE'] = 'A';
251
252global $MY_SELF; // fix apcu
253global $MY_SELF_WO_SORT; // fix apcu
254$MY_SELF_WO_SORT = "$PHP_SELF" . "?SCOPE=" . $MYREQUEST['SCOPE'] . "&COUNT=" . $MYREQUEST['COUNT'] . "&SEARCH=" . $MYREQUEST['SEARCH'] . "&TYPECACHE=" . $MYREQUEST['TYPECACHE'] . "&ZOOM=" . $MYREQUEST['ZOOM'] . "&EXTRA=" . $MYREQUEST['EXTRA'] . "&WHERE=" . $MYREQUEST['WHERE'] . "&exec=" . $MYREQUEST['exec'] . "&OB=" . $MYREQUEST['OB'];
255$MY_SELF         = $MY_SELF_WO_SORT . "&S_KEY=" . $MYREQUEST['S_KEY'] . "&SORT=" . $MYREQUEST['SORT'];
256$self            = "http" . (!empty($_SERVER['HTTPS']) ? "s" : "") . "://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
257
258global $IMG_BASE;
259$IMG_BASE = "$PHP_SELF" . "?exec=" . $MYREQUEST['exec'];
260
261// authentication needed?
262//
263if (!USE_AUTHENTICATION) {
264        $AUTHENTICATED = 1;
265} else {
266        $AUTHENTICATED = 0;
267        if (ADMIN_PASSWORD != 'password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
268               
269                if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME || $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
270                        Header("WWW-Authenticate: Basic realm=\"APC Login\"");
271                        Header("HTTP/1.0 401 Unauthorized");
272                       
273                        echo <<<EOB
274                                <html><body>
275                                <h1>Rejected!</h1>
276                                <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
277                                <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
278                                </body></html>
279EOB;
280                        exit;
281                       
282                } else {
283                        $AUTHENTICATED = 1;
284                }
285        }
286}
287
288// clear cache
289if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
290        apcu_clear_cache();
291}
292
293if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
294        apcu_delete($MYREQUEST['DU']);
295}
296
297if (!function_exists('apcu_cache_info')) {
298        echo "No cache info available.  APC does not appear to be running.";
299        exit;
300}
301
302$cache = apcu_cache_info();
303
304$mem = apcu_sma_info();
305
306// don't cache this page
307//
308header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
309header("Cache-Control: post-check=0, pre-check=0", false);
310header("Pragma: no-cache"); // HTTP/1.0
311
312function duration($ts)
313{
314        global $time;
315        $years = (int) ((($time - $ts) / (7 * 86400)) / 52.177457);
316        $rem   = (int) (($time - $ts) - ($years * 52.177457 * 7 * 86400));
317        $weeks = (int) (($rem) / (7 * 86400));
318        $days  = (int) (($rem) / 86400) - $weeks * 7;
319        $hours = (int) (($rem) / 3600) - $days * 24 - $weeks * 7 * 24;
320        $mins  = (int) (($rem) / 60) - $hours * 60 - $days * 24 * 60 - $weeks * 7 * 24 * 60;
321        $str   = '';
322        if ($years == 1)
323                $str .= "$years year, ";
324        if ($years > 1)
325                $str .= "$years years, ";
326        if ($weeks == 1)
327                $str .= "$weeks week, ";
328        if ($weeks > 1)
329                $str .= "$weeks weeks, ";
330        if ($days == 1)
331                $str .= "$days day,";
332        if ($days > 1)
333                $str .= "$days days,";
334        if ($hours == 1)
335                $str .= " $hours hour and";
336        if ($hours > 1)
337                $str .= " $hours hours and";
338        if ($mins == 1)
339                $str .= " 1 minute";
340        else
341                $str .= " $mins minutes";
342        return $str;
343}
344
345// create graphics
346//
347function graphics_avail()
348{
349        return extension_loaded('gd');
350}
351if (isset($MYREQUEST['IMG'])) {
352        if (!graphics_avail()) {
353                exit(0);
354        }
355       
356        function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1, $color2, $text = '', $placeindex = 0)
357        {
358                $r = $diameter / 2;
359                $w = deg2rad((360 + $start + ($end - $start) / 2) % 360);
360               
361               
362                if (function_exists("imagefilledarc")) {
363                        // exists only if GD 2.0.1 is avaliable
364                        imagefilledarc($im, $centerX + 1, $centerY + 1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
365                        imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
366                        imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL | IMG_ARC_EDGED);
367                } else {
368                        imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
369                        imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
370                        imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start + 1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
371                        imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end - 1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
372                        imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
373                        imagefill($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $color2);
374                }
375                if ($text) {
376                        if ($placeindex > 0) {
377                                imageline($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $diameter, $placeindex * 12, $color1);
378                                imagestring($im, 4, $diameter, $placeindex * 12, $text, $color1);
379                               
380                        } else {
381                                imagestring($im, 4, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $text, $color1);
382                        }
383                }
384        }
385       
386        function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1, $text, $placeindex = 0)
387        {
388                $r = $diameter / 2;
389                $w = deg2rad((360 + $start + ($end - $start) / 2) % 360);
390               
391                if ($placeindex > 0) {
392                        imageline($im, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $diameter, $placeindex * 12, $color1);
393                        imagestring($im, 4, $diameter, $placeindex * 12, $text, $color1);
394                       
395                } else {
396                        imagestring($im, 4, $centerX + $r * cos($w) / 2, $centerY + $r * sin($w) / 2, $text, $color1);
397                }
398        }
399       
400        function fill_box($im, $x, $y, $w, $h, $color1, $color2, $text = '', $placeindex = '')
401        {
402                global $col_black;
403                $x1 = $x + $w - 1;
404                $y1 = $y + $h - 1;
405               
406                imagerectangle($im, $x, $y1, $x1 + 1, $y + 1, $col_black);
407                if ($y1 > $y)
408                        imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
409                else
410                        imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
411                imagerectangle($im, $x, $y1, $x1, $y, $color1);
412                if ($text) {
413                        if ($placeindex > 0) {
414                               
415                                if ($placeindex < 16) {
416                                        $px = 5;
417                                        $py = $placeindex * 12 + 6;
418                                        imagefilledrectangle($im, $px + 90, $py + 3, $px + 90 - 4, $py - 3, $color2);
419                                        imageline($im, $x, $y + $h / 2, $px + 90, $py, $color2);
420                                        imagestring($im, 2, $px, $py - 6, $text, $color1);
421                                       
422                                } else {
423                                        if ($placeindex < 31) {
424                                                $px = $x + 40 * 2;
425                                                $py = ($placeindex - 15) * 12 + 6;
426                                        } else {
427                                                $px = $x + 40 * 2 + 100 * intval(($placeindex - 15) / 15);
428                                                $py = ($placeindex % 15) * 12 + 6;
429                                        }
430                                        imagefilledrectangle($im, $px, $py + 3, $px - 4, $py - 3, $color2);
431                                        imageline($im, $x + $w, $y + $h / 2, $px, $py, $color2);
432                                        imagestring($im, 2, $px + 2, $py - 6, $text, $color1);
433                                }
434                        } else {
435                                imagestring($im, 4, $x + 5, $y1 - 16, $text, $color1);
436                        }
437                }
438        }
439       
440       
441        $size = GRAPH_SIZE / 3; // image size
442        if ($MYREQUEST['IMG'] == 3)
443                $image = imagecreate(3 * $size + 200, 2 * $size + 150);
444        else
445                $image = imagecreate($size + 50, $size + 10);
446       
447        $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
448        $col_red   = imagecolorallocate($image, 0xD0, 0x60, 0x30);
449        $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
450        $col_black = imagecolorallocate($image, 0, 0, 0);
451        imagecolortransparent($image, $col_white);
452       
453        switch ($MYREQUEST['IMG']) {
454               
455                case 1:
456                        $s    = $mem['num_seg'] * $mem['seg_size'];
457                        $a    = $mem['avail_mem'];
458                        $x    = $y = $size / 2;
459                        $fuzz = 0.000001;
460                       
461                        // This block of code creates the pie chart.  It is a lot more complex than you
462                        // would expect because we try to visualize any memory fragmentation as well.
463                        $angle_from       = 0;
464                        $string_placement = array();
465                        for ($i = 0; $i < $mem['num_seg']; $i++) {
466                                $ptr  = 0;
467                                $free = $mem['block_lists'][$i];
468                                uasort($free, 'block_sort');
469                                foreach ($free as $block) {
470                                        if ($block['offset'] != $ptr) { // Used block
471                                                $angle_to = $angle_from + ($block['offset'] - $ptr) / $s;
472                                                if (($angle_to + $fuzz) > 1)
473                                                        $angle_to = 1;
474                                                if (($angle_to * 360) - ($angle_from * 360) >= 1) {
475                                                        fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_red);
476                                                        if (($angle_to - $angle_from) > 0.05) {
477                                                                array_push($string_placement, array(
478                                                                        $angle_from,
479                                                                        $angle_to
480                                                                ));
481                                                        }
482                                                }
483                                                $angle_from = $angle_to;
484                                        }
485                                        $angle_to = $angle_from + ($block['size']) / $s;
486                                        if (($angle_to + $fuzz) > 1)
487                                                $angle_to = 1;
488                                        if (($angle_to * 360) - ($angle_from * 360) >= 1) {
489                                                fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_green);
490                                                if (($angle_to - $angle_from) > 0.05) {
491                                                        array_push($string_placement, array(
492                                                                $angle_from,
493                                                                $angle_to
494                                                        ));
495                                                }
496                                        }
497                                        $angle_from = $angle_to;
498                                        $ptr        = $block['offset'] + $block['size'];
499                                }
500                                if ($ptr < $mem['seg_size']) { // memory at the end
501                                        $angle_to = $angle_from + ($mem['seg_size'] - $ptr) / $s;
502                                        if (($angle_to + $fuzz) > 1)
503                                                $angle_to = 1;
504                                        fill_arc($image, $x, $y, $size, $angle_from * 360, $angle_to * 360, $col_black, $col_red);
505                                        if (($angle_to - $angle_from) > 0.05) {
506                                                array_push($string_placement, array(
507                                                        $angle_from,
508                                                        $angle_to
509                                                ));
510                                        }
511                                }
512                        }
513                        foreach ($string_placement as $angle) {
514                                text_arc($image, $x, $y, $size, $angle[0] * 360, $angle[1] * 360, $col_black, bsize($s * ($angle[1] - $angle[0])));
515                        }
516                        break;
517               
518                case 2:
519                        $s = $cache['num_hits'] + $cache['num_misses'];
520                        $a = $cache['num_hits'];
521                       
522                        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));
523                        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));
524                        break;
525               
526                case 3:
527                        $s = $mem['num_seg'] * $mem['seg_size'];
528                        $a = $mem['avail_mem'];
529                        $x = 130;
530                        $y = 1;
531                        $j = 1;
532                       
533                        // This block of code creates the bar chart.  It is a lot more complex than you
534                        // would expect because we try to visualize any memory fragmentation as well.
535                        for ($i = 0; $i < $mem['num_seg']; $i++) {
536                                $ptr  = 0;
537                                $free = $mem['block_lists'][$i];
538                                uasort($free, 'block_sort');
539                                foreach ($free as $block) {
540                                        if ($block['offset'] != $ptr) { // Used block
541                                                $h = (GRAPH_SIZE - 5) * ($block['offset'] - $ptr) / $s;
542                                                if ($h > 0) {
543                                                        $j++;
544                                                        if ($j < 75)
545                                                                fill_box($image, $x, $y, 50, $h, $col_black, $col_red, bsize($block['offset'] - $ptr), $j);
546                                                        else
547                                                                fill_box($image, $x, $y, 50, $h, $col_black, $col_red);
548                                                }
549                                                $y += $h;
550                                        }
551                                        $h = (GRAPH_SIZE - 5) * ($block['size']) / $s;
552                                        if ($h > 0) {
553                                                $j++;
554                                                if ($j < 75)
555                                                        fill_box($image, $x, $y, 50, $h, $col_black, $col_green, bsize($block['size']), $j);
556                                                else
557                                                        fill_box($image, $x, $y, 50, $h, $col_black, $col_green);
558                                        }
559                                        $y += $h;
560                                        $ptr = $block['offset'] + $block['size'];
561                                }
562                                if ($ptr < $mem['seg_size']) { // memory at the end
563                                        $h = (GRAPH_SIZE - 5) * ($mem['seg_size'] - $ptr) / $s;
564                                        if ($h > 0) {
565                                                fill_box($image, $x, $y, 50, $h, $col_black, $col_red, bsize($mem['seg_size'] - $ptr), $j++);
566                                        }
567                                }
568                        }
569                        break;
570               
571                case 4:
572                        $s = $cache['num_hits'] + $cache['num_misses'];
573                        $a = $cache['num_hits'];
574                       
575                        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));
576                        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));
577                        break;
578        }
579       
580        header("Content-type: image/png");
581        imagepng($image);
582        exit;
583}
584
585// pretty printer for byte values
586//
587function bsize($s)
588{
589        foreach (array(
590                '',
591                'K',
592                'M',
593                'G'
594        ) as $i => $k) {
595                if ($s < 1024)
596                        break;
597                $s /= 1024;
598        }
599        return sprintf("%5.1f %sBytes", $s, $k);
600}
601
602// sortable table header in "scripts for this host" view
603function sortheader($key, $name, $extra = '')
604{
605        global $MYREQUEST;
606        global $MY_SELF_WO_SORT; // fix apcu : il faut global ici aussi
607       
608        // fix apcu l'affichage des headers ne doit pas changer $MYREQUEST
609        $SORT = $MYREQUEST['SORT'];
610        if (!$SORT)
611                $SORT = 'D';
612        if ($MYREQUEST['S_KEY'] == $key)
613                $SORT = (($SORT == 'A') ? 'D' : 'A');
614        $url = "$MY_SELF_WO_SORT$extra&S_KEY=$key&SORT=$SORT";
615        return "<a class=sortable href='$url'>$name</a>";
616}
617
618// create menu entry
619function menu_entry($ob, $title)
620{
621        global $MYREQUEST;
622        global $MY_SELF; // fix apcu
623        if ($MYREQUEST['OB'] != $ob) {
624                return "<li><a href='" . parametre_url($MY_SELF, 'OB', $ob) . "'>$title</a></li>";
625        } else if (empty($MYREQUEST['SH'])) {
626                return "<li><span class=active>$title</span></li>";
627        } else {
628                return "<li><a class=\"child_active\" href='$MY_SELF'>$title</a></li>";
629        }
630}
631
632function put_login_link($s = "Login")
633{
634        global $MY_SELF, $MYREQUEST, $AUTHENTICATED;
635        // needs ADMIN_PASSWORD to be changed!
636        //
637        if (!USE_AUTHENTICATION) {
638                return;
639        } else if (ADMIN_PASSWORD == 'password') {
640                print <<<EOB
641                        <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
642EOB;
643        } else if ($AUTHENTICATED) {
644                print <<<EOB
645                        '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
646EOB;
647        } else {
648                print <<<EOB
649                        <a href="$MY_SELF&LO=1">$s</a>
650EOB;
651        }
652}
653
654function block_sort($array1, $array2)
655{
656        if ($array1['offset'] > $array2['offset']) {
657                return 1;
658        } else {
659                return -1;
660        }
661}
662
663
664?>
665<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
666<html>
667<head><title>APCu INFO <?php
668echo $host;
669?></title>
670<style><!--
671body { background:white; font-size:100.01%; margin:0; padding:0; }
672body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
673* html body   {font-size:0.8em}
674* html p      {font-size:0.8em}
675* html td     {font-size:0.8em}
676* html th     {font-size:0.8em}
677* html input  {font-size:0.8em}
678* html submit {font-size:0.8em}
679td { vertical-align:top }
680a { color:black; font-weight:none; text-decoration:none; }
681a:hover { text-decoration:underline; }
682div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
683
684
685div.head div.login {
686        position:absolute;
687        right: 1em;
688        top: 1.2em;
689        color:white;
690        width:6em;
691        }
692div.head div.login a {
693        position:absolute;
694        right: 0em;
695        background:rgb(119,123,180);
696        border:solid rgb(102,102,153) 2px;
697        color:white;
698        font-weight:bold;
699        padding:0.1em 0.5em 0.1em 0.5em;
700        text-decoration:none;
701        }
702div.head div.login a:hover {
703        background:rgb(193,193,244);
704        }
705
706h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
707* html h1.apc { margin-bottom:-7px; }
708h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
709h1.apc div.logo {display: inline}
710h1.apc div.logo span.logo {
711        background:rgb(119,123,180);
712        color:black;
713        border-right: solid black 1px;
714        border-bottom: solid black 1px;
715        font-style:italic;
716        font-size:1em;
717        padding-left:1.2em;
718        padding-right:1.2em;
719        text-align:right;
720        }
721h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
722h1.apc div.nameinfo { color:white; display:inline; font-size:0.6em; margin-left: 1em; }
723h1.apc div.nameinfo a { color:white; margin-left: 3em; }
724h1.apc div.nameinfo img {margin-bottom: -10px; margin-right : 1em;}
725h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
726hr.apc { display: none; }
727
728ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
729ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
730ol.menu a {
731        background:rgb(153,153,204);
732        border:solid rgb(102,102,153) 2px;
733        color:white;
734        font-weight:bold;
735        margin-right:0em;
736        padding:0.1em 0.5em 0.1em 0.5em;
737        text-decoration:none;
738        margin-left: 5px;
739        }
740ol.menu a.child_active {
741        background:rgb(153,153,204);
742        border:solid rgb(102,102,153) 2px;
743        color:white;
744        font-weight:bold;
745        margin-right:0em;
746        padding:0.1em 0.5em 0.1em 0.5em;
747        text-decoration:none;
748        border-left: solid black 5px;
749        margin-left: 0px;
750        }
751ol.menu span.active {
752        background:rgb(153,153,204);
753        border:solid rgb(102,102,153) 2px;
754        color:black;
755        font-weight:bold;
756        margin-right:0em;
757        padding:0.1em 0.5em 0.1em 0.5em;
758        text-decoration:none;
759        border-left: solid black 5px;
760        }
761ol.menu span.inactive {
762        background:rgb(193,193,244);
763        border:solid rgb(182,182,233) 2px;
764        color:white;
765        font-weight:bold;
766        margin-right:0em;
767        padding:0.1em 0.5em 0.1em 0.5em;
768        text-decoration:none;
769        margin-left: 5px;
770        }
771ol.menu a:hover {
772        background:rgb(193,193,244);
773        text-decoration:none;
774        }
775
776
777div.info {
778        background:rgb(204,204,204);
779        border:solid rgb(204,204,204) 1px;
780        margin-bottom:1em;
781        }
782div.info h2 {
783        background:rgb(204,204,204);
784        color:black;
785        font-size:1em;
786        margin:0;
787        padding:0.1em 1em 0.1em 1em;
788        }
789div.info table {
790        border:solid rgb(204,204,204) 1px;
791        border-spacing:0;
792        width:100%;
793        }
794div.info table th {
795        background:rgb(204,204,204);
796        color:white;
797        margin:0;
798        padding:0.1em 1em 0.1em 1em;
799        }
800div.info table th a.sortable { color:black; }
801div.info table tr.tr-0 { background:rgb(238,238,238); }
802div.info table tr.tr-1 { background:rgb(221,221,221); }
803div.info table td { padding:0.3em 1em 0.3em 1em; }
804div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
805div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
806div.info table td h3 {
807        color:black;
808        font-size:1.1em;
809        margin-left:-0.3em;
810        }
811
812div.graph { margin-bottom:1em }
813div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
814div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
815div.graph table td.td-0 { background:rgb(238,238,238); }
816div.graph table td.td-1 { background:rgb(221,221,221); }
817div.graph table td { padding:0.2em 1em 0.4em 1em; }
818
819div.div1,div.div2 { margin-bottom:1em; width:35em; }
820div.div3 { position:absolute; left:40em; top:1em; width:580px; }
821//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
822
823div.sorting { margin:1.5em 0em 1.5em 2em }
824.center { text-align:center }
825.aright { position:absolute;right:1em }
826.right { text-align:right }
827.ok { color:rgb(0,200,0); font-weight:bold}
828.failed { color:rgb(200,0,0); font-weight:bold}
829
830span.box {
831        border: black solid 1px;
832        border-right:solid black 2px;
833        border-bottom:solid black 2px;
834        padding:0 0.5em 0 0.5em;
835        margin-right:1em;
836}
837span.green { background:#60F060; padding:0 0.5em 0 0.5em}
838span.red { background:#D06030; padding:0 0.5em 0 0.5em }
839
840div.authneeded {
841        background:rgb(238,238,238);
842        border:solid rgb(204,204,204) 1px;
843        color:rgb(200,0,0);
844        font-size:1.2em;
845        font-weight:bold;
846        padding:2em;
847        text-align:center;
848        }
849
850input {
851        background:rgb(153,153,204);
852        border:solid rgb(102,102,153) 2px;
853        color:white;
854        font-weight:bold;
855        margin-right:1em;
856        padding:0.1em 0.5em 0.1em 0.5em;
857        }
858
859/* xray styles */
860xmp { display: inline }
861.menuzoom {
862        border :  1px solid grey;
863        border-radius: 3px;
864        padding : 0px 5px 0px 5px;
865}
866
867//-->
868</style>
869</head>
870<body>
871<div class="head">
872        <h1 class="apc">
873                <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APCu">APCu</a></span></div>
874                <div class="nameinfo" style="display: inline">
875                        User Cache
876                        <a href='https://contrib.spip.net/4946'>
877                        <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=' >
878                        XRay pour SPIP
879                        </a>
880                </div>
881                </a>
882        </h1>
883        <div class="login">
884        <?php
885put_login_link();
886?>
887        </div>
888        <hr class="apc">
889</div>
890
891<?php
892// Display main Menu
893echo <<<EOB
894        <ol class=menu>
895        <li><a href="$MY_SELF&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
896EOB;
897echo menu_entry(OB_HOST_STATS, 'View Host Stats'), menu_entry(OB_USER_CACHE, 'User Cache Entries'), menu_entry(OB_VERSION_CHECK, 'Version Check');
898
899if ($AUTHENTICATED) {
900        echo <<<EOB
901                <li><a class="aright" href="$MY_SELF&CC=1" onClick="javascript:return confirm('Are you sure?');">Clear Cache</a></li>
902EOB;
903}
904echo <<<EOB
905        </ol>
906EOB;
907
908
909// CONTENT
910echo <<<EOB
911        <div class=content>
912EOB;
913
914// MAIN SWITCH STATEMENT
915
916switch ($MYREQUEST['OB']) {
917        // -----------------------------------------------
918        // Host Stats
919        // -----------------------------------------------
920        case OB_HOST_STATS:
921                $mem_size         = $mem['num_seg'] * $mem['seg_size'];
922                $mem_avail        = $mem['avail_mem'];
923                $mem_used         = $mem_size - $mem_avail;
924                $seg_size         = bsize($mem['seg_size']);
925                $req_rate_user    = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits'] + $cache['num_misses']) / ($time - $cache['start_time'])) : 0);
926                $hit_rate_user    = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits']) / ($time - $cache['start_time'])) : 0);
927                $miss_rate_user   = sprintf("%.2f", $cache['num_misses'] ? (($cache['num_misses']) / ($time - $cache['start_time'])) : 0);
928                $insert_rate_user = sprintf("%.2f", $cache['num_inserts'] ? (($cache['num_inserts']) / ($time - $cache['start_time'])) : 0);
929                $apcversion       = phpversion('apcu');
930                $phpversion       = phpversion();
931                $number_vars      = $cache['num_entries'];
932                $size_vars        = bsize($cache['mem_size']);
933                $i                = 0;
934                $_namespace       = _CACHE_NAMESPACE;
935                echo <<< EOB
936                <div class="info div1"><h2>Mémoization SPIP</h2>
937                <table cellspacing=0><tbody>
938                <tr class=tr-0><td class=td-0>_CACHE_NAMESPACE</td><td>$_namespace</td></tr>
939                </table></div>
940EOB;
941                echo <<< EOB
942                <div class="info div1"><h2>General Cache Information</h2>
943                <table cellspacing=0><tbody>
944                <tr class=tr-0><td class=td-0>APCu Version</td><td>$apcversion</td></tr>
945                <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
946EOB;
947               
948                if (!empty($_SERVER['SERVER_NAME']))
949                        echo "<tr class=tr-0><td class=td-0>APCu Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
950                if (!empty($_SERVER['SERVER_SOFTWARE']))
951                        echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
952               
953                echo <<<EOB
954                <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
955    <br/> ({$cache['memory_type']} memory)
956    </td></tr>
957EOB;
958                echo '<tr class=tr-1><td class=td-0>Start Time</td><td>', date(DATE_FORMAT, $cache['start_time']), '</td></tr>';
959                echo '<tr class=tr-0><td class=td-0>Uptime</td><td>', duration($cache['start_time']), '</td></tr>';
960                echo <<<EOB
961                </tbody></table>
962                </div>
963
964                <div class="info div1"><h2>Cache Information</h2>
965                <table cellspacing=0>
966                <tbody>
967                <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
968                        <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
969                        <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
970                        <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
971                        <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
972                        <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
973                        <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
974                        <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
975                </tbody>
976                </table>
977                </div>
978
979                <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
980EOB;
981               
982                $j = 0;
983                foreach (ini_get_all('apcu') as $k => $v) {
984                        echo "<tr class=tr-$j><td class=td-0>", $k, "</td><td>", str_replace(',', ',<br />', $v['local_value']), "</td></tr>\n";
985                        $j = 1 - $j;
986                }
987               
988                if ($mem['num_seg'] > 1 || $mem['num_seg'] == 1 && count($mem['block_lists'][0]) > 1)
989                        $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
990                else
991                        $mem_note = "Memory Usage";
992               
993                echo <<< EOB
994                </tbody></table>
995                </div>
996
997                <div class="graph div3"><h2>Host Status Diagrams</h2>
998                <table cellspacing=0><tbody>
999EOB;
1000                $size = 'width=' . (GRAPH_SIZE * 2 / 3) . ' height=' . (GRAPH_SIZE / 2);
1001                echo <<<EOB
1002                <tr>
1003                <td class=td-0>$mem_note</td>
1004                <td class=td-1>Hits &amp; Misses</td>
1005                </tr>
1006EOB;
1007               
1008                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) . sprintf(" (%.1f%%)", $mem_avail * 100 / $mem_size), "</td>\n", '<td class=td-1><span class="green box">&nbsp;</span>Hits: ', $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / ($cache['num_hits'] + $cache['num_misses'])), "</td>\n", '</tr>', '<tr>', '<td class=td-0><span class="red box">&nbsp;</span>Used: ', bsize($mem_used) . sprintf(" (%.1f%%)", $mem_used * 100 / $mem_size), "</td>\n", '<td class=td-1><span class="red box">&nbsp;</span>Misses: ', $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / ($cache['num_hits'] + $cache['num_misses'])), "</td>\n";
1009                echo <<< EOB
1010                </tr>
1011                </tbody></table>
1012
1013                <br/>
1014                <h2>Detailed Memory Usage and Fragmentation</h2>
1015                <table cellspacing=0><tbody>
1016                <tr>
1017                <td class=td-0 colspan=2><br/>
1018EOB;
1019               
1020                // Fragementation: (freeseg - 1) / total_seg
1021                $nseg = $freeseg = $fragsize = $freetotal = 0;
1022                for ($i = 0; $i < $mem['num_seg']; $i++) {
1023                        $ptr = 0;
1024                        foreach ($mem['block_lists'][$i] as $block) {
1025                                if ($block['offset'] != $ptr) {
1026                                        ++$nseg;
1027                                }
1028                                $ptr = $block['offset'] + $block['size'];
1029                                /* Only consider blocks <5M for the fragmentation % */
1030                                if ($block['size'] < (5 * 1024 * 1024))
1031                                        $fragsize += $block['size'];
1032                                $freetotal += $block['size'];
1033                        }
1034                        $freeseg += count($mem['block_lists'][$i]);
1035                }
1036               
1037                if ($freeseg > 1) {
1038                        $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize / $freetotal) * 100, bsize($fragsize), bsize($freetotal), $freeseg);
1039                } else {
1040                        $frag = "0%";
1041                }
1042               
1043                if (graphics_avail()) {
1044                        $size = 'width=' . (2 * GRAPH_SIZE + 150) . ' height=' . (GRAPH_SIZE + 10);
1045                        echo <<<EOB
1046                        <img alt="" $size src="{$IMG_BASE}&IMG=3&$time">
1047EOB;
1048                }
1049                echo <<<EOB
1050                </br>Fragmentation: $frag
1051                </td>
1052                </tr>
1053EOB;
1054                if (isset($mem['adist'])) {
1055                        foreach ($mem['adist'] as $i => $v) {
1056                                $cur = pow(2, $i);
1057                                $nxt = pow(2, $i + 1) - 1;
1058                                if ($i == 0)
1059                                        $range = "1";
1060                                else
1061                                        $range = "$cur - $nxt";
1062                                echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
1063                        }
1064                }
1065                echo <<<EOB
1066                </tbody></table>
1067                </div>
1068EOB;
1069               
1070                break;
1071       
1072       
1073        // -----------------------------------------------
1074        // User Cache Entries
1075        // -----------------------------------------------
1076        case OB_USER_CACHE:
1077                if (!$AUTHENTICATED) {
1078                        echo '<div class="error">You need to login to see the user values here!<br/>&nbsp;<br/>';
1079                        put_login_link("Login now!");
1080                        echo '</div>';
1081                        break;
1082                }
1083                $fieldname    = 'info';
1084                $fieldheading = 'User Entry Label';
1085                $fieldkey     = 'info';
1086               
1087                $cols = 6;
1088                echo <<<EOB
1089                <div class=sorting><form><p>Scope:
1090                <input type=hidden name=OB value={$MYREQUEST['OB']}>
1091                <input type=hidden name=exec value={$MYREQUEST['exec']}>
1092                <select name=SCOPE  onChange="form.submit()">
1093EOB;
1094                echo '<option value=A', $MYREQUEST['SCOPE'] == 'A' ? ' selected' : '', '>Active</option>
1095                        <option value=D', $MYREQUEST['SCOPE'] == 'D' ? ' selected' : '', '>Deleted</option>
1096                </select>
1097                 Sorting:
1098                <select name=S_KEY  onChange="form.submit()">
1099                        <option value=H', $MYREQUEST['S_KEY'] == 'H' ? ' selected' : '', '>Hits</option>
1100                        <option value=Z', $MYREQUEST['S_KEY'] == 'Z' ? ' selected' : '', '>Size</option>
1101                        <option value=S', $MYREQUEST['S_KEY'] == 'S' ? ' selected' : '', '>$fieldheading</option>
1102                        <option value=A', $MYREQUEST['S_KEY'] == 'A' ? ' selected' : '', '>Last accessed</option>
1103                        <option value=M', $MYREQUEST['S_KEY'] == 'M' ? ' selected' : '', '>Last modified</option>
1104                        <option value=C', $MYREQUEST['S_KEY'] == 'C' ? ' selected' : '', '>Created at</option>
1105                        <option value=D', $MYREQUEST['S_KEY'] == 'D' ? ' selected' : '', '>Deleted at</option>';
1106                if ($fieldname == 'info')
1107                        echo '<option value=D', $MYREQUEST['S_KEY'] == 'T' ? ' selected' : '', '>Timeout</option>';
1108               
1109                echo '</select>
1110                <select name=SORT  onChange="form.submit()">', 
1111                        '<option value=D', $MYREQUEST['SORT'] == 'D' ? ' selected' : '', '>DESC</option>', 
1112                        '<option value=A', $MYREQUEST['SORT'] == 'A' ? ' selected' : '', '>ASC</option>', 
1113                '</select>
1114                &nbsp;&nbsp;<b>HTML:</b>
1115                <select name=ZOOM  onChange="form.submit()">
1116                        <option value=TEXTECOURT', $MYREQUEST['ZOOM'] == 'TEXTECOURT' ? ' selected' : '', '>Courts</option>
1117                        <option value=TEXTELONG', $MYREQUEST['ZOOM'] == 'TEXTELONG' ? ' selected' : '', '>Entiers</option>
1118                </select>
1119                &nbsp;&nbsp;<b>Affichage extra:</b>
1120                <select name=EXTRA  onChange="form.submit()">
1121                        <option value="" ', $MYREQUEST['EXTRA'] == '' ? ' selected' : '', '></option>
1122                        <option value=CONTEXTE ', $MYREQUEST['EXTRA'] == 'CONTEXTE' ? ' selected' : '', '>Contexte</option>
1123                        <option value=CONTEXTES_SPECIAUX ', $MYREQUEST['EXTRA'] == 'CONTEXTES_SPECIAUX' ? ' selected' : '', '>Contextes spécifiques</option>
1124                        <option value=INFO_AUTEUR ', $MYREQUEST['EXTRA'] == 'INFO_AUTEUR' ? ' selected' : '', '>Infos auteur</option>
1125                        <option value=INVALIDEURS ', $MYREQUEST['EXTRA'] == 'INVALIDEURS' ? ' selected' : '', '>Invalideurs</option>
1126                        <option value=INVALIDEURS_SPECIAUX ', $MYREQUEST['EXTRA'] == 'INVALIDEURS_SPECIAUX' ? ' selected' : '', '>Invalideurs spécifiques</option>
1127                        <option value=INCLUSIONS ', $MYREQUEST['EXTRA'] == 'INCLUSIONS' ? ' selected' : '', '>&lt;INCLURE&gt;</option>
1128                        <option value=MACROSESSIONS ', $MYREQUEST['EXTRA'] == 'MACROSESSIONS' ? ' selected' : '', '>#_SESSION</option>
1129                </select>
1130                <p><b>Types cache:</b>
1131                <select name=TYPECACHE  onChange="form.submit()">
1132                        <option value=ALL', $MYREQUEST['TYPECACHE'] == 'ALL' ? ' selected' : '', '>Tous</option>
1133                        <option value=SESSIONS', $MYREQUEST['TYPECACHE'] == 'SESSIONS' ? ' selected' : '', '>Sessionnés</option>
1134                        <option value=SESSIONS_AUTH', $MYREQUEST['TYPECACHE'] == 'SESSIONS_AUTH' ? ' selected' : '', '>Sessionnés identifiés</option>
1135                        <option value=SESSIONS_NONAUTH', $MYREQUEST['TYPECACHE'] == 'SESSIONS_NONAUTH' ? ' selected' : '', '>Sessionnés non identifiés</option>
1136                        <option value=FORMULAIRES', $MYREQUEST['TYPECACHE'] == 'FORMULAIRES' ? ' selected' : '', '>Formulaires</option>
1137                </select>
1138                <select name=COUNT onChange="form.submit()">
1139                        <option value=10 ', $MYREQUEST['COUNT'] == '10' ? ' selected' : '', '>Top 10</option>
1140                        <option value=20 ', $MYREQUEST['COUNT'] == '20' ? ' selected' : '', '>Top 20</option>
1141                        <option value=50 ', $MYREQUEST['COUNT'] == '50' ? ' selected' : '', '>Top 50</option>
1142                        <option value=100', $MYREQUEST['COUNT'] == '100' ? ' selected' : '', '>Top 100</option>
1143                        <option value=150', $MYREQUEST['COUNT'] == '150' ? ' selected' : '', '>Top 150</option>
1144                        <option value=200', $MYREQUEST['COUNT'] == '200' ? ' selected' : '', '>Top 200</option>
1145                        <option value=500', $MYREQUEST['COUNT'] == '500' ? ' selected' : '', '>Top 500</option>
1146                        <option value=0  ', $MYREQUEST['COUNT'] == '0' ? ' selected' : '', '>All</option>
1147                </select>
1148                &nbsp;&nbsp;&nbsp;
1149                Chercher: <input name=SEARCH value="', $MYREQUEST['SEARCH'], '" type=text size=25/>
1150                <b>Dans:</b>
1151                <select name=WHERE onChange="form.submit()">
1152                        <option value="" ', $MYREQUEST['WHERE'] == '' ? ' selected' : '', '>Noms des caches</option>
1153                        <option value="ALL" ', $MYREQUEST['WHERE'] == 'ALL' ? ' selected' : '', '>Tout le contenu</option>
1154                        <option value="HTML" ', $MYREQUEST['WHERE'] == 'HTML' ? ' selected' : '', '>HTML</option>
1155                        <option value="META" ', $MYREQUEST['WHERE'] == 'META' ? ' selected' : '', '>Métadonnées</option>
1156                </select>
1157                &nbsp;&nbsp;&nbsp;
1158                <input type=submit value="GO!">
1159                </p></form></div>';
1160               
1161                if (isset($MYREQUEST['SEARCH'])) {
1162                        // Don't use preg_quote because we want the user to be able to specify a
1163                        // regular expression subpattern.
1164                        $MYREQUEST['SEARCH'] = '/' . str_replace('/', '\\/', $MYREQUEST['SEARCH']) . '/i';
1165                        if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
1166                                echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
1167                                break;
1168                        }
1169                }
1170                echo '<div class="info"><table cellspacing=0><tbody>', '<tr>', '<th>', sortheader('S', $fieldheading), '</th>', '<th>', sortheader('H', 'Hits'), '</th>', '<th>', sortheader('Z', 'Size'), '</th>', '<th>', sortheader('A', 'Last accessed'), '</th>', '<th>', sortheader('M', 'Last modified'), '</th>', '<th>', sortheader('C', 'Created at'), '</th>';
1171               
1172                if ($fieldname == 'info') {
1173                        $cols += 2;
1174                        echo '<th>', sortheader('T', 'Timeout'), '</th>';
1175                }
1176                echo '<th>', sortheader('D', 'Deleted at'), '</th></tr>';
1177               
1178                // builds list with alpha numeric sortable keys
1179                //
1180                $list = array();
1181               
1182                foreach ($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
1183                        switch ($MYREQUEST['S_KEY']) {
1184                                case 'A':
1185                                        $k = sprintf('%015d-', $entry['access_time']);
1186                                        break;
1187                                case 'H':
1188                                        $k = sprintf('%015d-', $entry['num_hits']);
1189                                        break;
1190                                case 'Z':
1191                                        $k = sprintf('%015d-', $entry['mem_size']);
1192                                        break;
1193                                case 'M':
1194                                        $k = sprintf('%015d-', $entry['mtime']);
1195                                        break;
1196                                case 'C':
1197                                        $k = sprintf('%015d-', $entry['creation_time']);
1198                                        break;
1199                                case 'T':
1200                                        $k = sprintf('%015d-', $entry['ttl']);
1201                                        break;
1202                                case 'D':
1203                                        $k = sprintf('%015d-', $entry['deletion_time']);
1204                                        break;
1205                                case 'S':
1206                                        $k = $entry["info"];
1207                                        break;
1208                        }
1209                        if (!$AUTHENTICATED) {
1210                                // hide all path entries if not logged in
1211                                $list[$k . $entry[$fieldname]] = preg_replace('/^.*(\\/|\\\\)/', '*hidden*/', $entry);
1212                        } else {
1213                                $list[$k . $entry[$fieldname]] = $entry;
1214                        }
1215                }
1216               
1217                if ($list) {
1218                        // sort list
1219                        //
1220                        switch ($MYREQUEST['SORT']) {
1221                                case "A":
1222                                        ksort($list);
1223                                        break;
1224                                case "D":
1225                                        krsort($list);
1226                                        break;
1227                                default:
1228                                        echo "...ah ben non pas de tri.";
1229                                        break;
1230                        }
1231                       
1232                        $TYPECACHE = (isset($MYREQUEST['TYPECACHE']) ? $MYREQUEST['TYPECACHE'] : 'ALL');
1233                        switch ($TYPECACHE) {
1234                                case 'ALL':
1235                                        $pattern_typecache = '';
1236                                        break;
1237                                case 'SESSIONS':
1238                                        $pattern_typecache = '/_([a-f0-9]{8}|)$/i';
1239                                        break;
1240                                case 'SESSIONS_AUTH':
1241                                        $pattern_typecache = '/_[a-f0-9]{8}$/i';
1242                                        break;
1243                                case 'SESSIONS_NONAUTH':
1244                                        $pattern_typecache = '/_$/i';
1245                                        break;
1246                                case 'FORMULAIRES':
1247                                        $pattern_typecache = '~formulaires/~i';
1248                                        break;
1249                        }
1250                       
1251                        // output list
1252                        $i = 0;
1253                        foreach ($list as $k => $entry) {
1254                                $data=$searched=null;
1255                                $success = false;
1256                                $tried_get_apc_data = false;
1257                                if ($MYREQUEST['SEARCH'] and $MYREQUEST['WHERE']) {
1258                                        $searched = $data = get_apc_data($entry['info'], $success);
1259                                        $tried_get_apc_data = true;
1260                                        switch ($MYREQUEST['WHERE']) {
1261                                        case 'ALL' :
1262                                                break;
1263                                        case 'HTML' :
1264                                                if (is_array($searched)) // !textwheel
1265                                                        $searched = $data['texte'];
1266                                                break;
1267                                        case 'META' :
1268                                                if (is_array($searched)) // !textwheel
1269                                                        unset($searched['texte']);
1270                                                break;
1271                                        default :
1272                                                die("Mauvaise valeur pour where : " . $MYREQUEST['WHERE']);
1273                                        }
1274                                };
1275
1276                                if ((!$pattern_typecache or preg_match($pattern_typecache, $entry[$fieldname]))
1277                                        and (!$MYREQUEST['SEARCH']
1278                                                or (!$MYREQUEST['WHERE']
1279                                                        and preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]))
1280                                                or ($MYREQUEST['WHERE']
1281                                                        and preg_match($MYREQUEST['SEARCH'].'m', print_r($searched,1))))) { 
1282                                        $sh = md5($entry["info"]);
1283                                       
1284                                        $field_value = htmlentities(strip_tags($entry[$fieldname], ''), ENT_QUOTES, 'UTF-8');
1285                                        if (defined('XRAY_NEPASAFFICHER_DEBUTNOMCACHE'))
1286                                                $field_value = str_replace(XRAY_NEPASAFFICHER_DEBUTNOMCACHE, '...', $field_value);
1287                                        echo '<tr id="key-' . $sh . '" class=tr-', $i % 2, '>', "<td class='td-0' style='position: relative'>
1288                        <a href='$MY_SELF&SH={$sh}#key-{$sh}'>$field_value</a>";
1289                                       
1290                                        if ($p = preg_match('/_([0-9a-f]{8})$/i', $field_value, $match) 
1291                                                and $MYREQUEST['SEARCH'] != "/{$match[1]}/i") {
1292                                                $url_session = parametre_url($MY_SELF, 'SEARCH', $match[1]);
1293                                                echo "<a href='$url_session' style='float: right'>[session]</a>";
1294                                        }
1295                                        if ($MYREQUEST['EXTRA'] and ($sh != $MYREQUEST["SH"]) // sinon yaura un zoom après et c'est inutile de répéter ici
1296                                                and (($tried_get_apc_data and $success)
1297                                                        or (!$tried_get_apc_data 
1298                                                                and ($data = get_apc_data($entry['info'], $success))))) {
1299                                                $extra = null;
1300                                                $liens = '';
1301                                                if (is_array($data)) {
1302                                                        switch ($MYREQUEST['EXTRA']) {
1303                                                        case 'CONTEXTE':
1304                                                                if (isset($data['contexte']))
1305                                                                        $extra = $data['contexte'];
1306                                                                else
1307                                                                        $extra = '(non défini)';
1308                                                                break;
1309                                                        case 'CONTEXTES_SPECIAUX':
1310                                                                if (isset($data['contexte'])) {
1311                                                                        $extra = $data['contexte'];
1312                                                                        foreach (array(
1313                                                                                'lang',
1314                                                                                'date',
1315                                                                                'date_default',
1316                                                                                'date_redac',
1317                                                                                'date_redac_default'
1318                                                                        ) as $ki)
1319                                                                                unset($extra[$ki]);
1320                                                                } else
1321                                                                        $extra = '(non défini)';
1322                                                                break;
1323                                                        case 'INFO_AUTEUR':
1324                                                                if (isset($data['contexte'])) {
1325                                                                        foreach (array(
1326                                                                                'id_auteur',
1327                                                                                'email',
1328                                                                                'nom',
1329                                                                                'statut',
1330                                                                                'login'
1331                                                                        ) as $ki)
1332                                                                                if (isset($data['contexte'][$ki]))
1333                                                                                        $extra[$ki] = $extra[$ki] = $data['contexte'][$ki];
1334                                                                };
1335                                                                break;
1336                                                        case 'INVALIDEURS':
1337                                                                if (isset ($data['invalideurs']))
1338                                                                        $extra = $data['invalideurs'];
1339                                                                break;
1340                                                        case 'INVALIDEURS_SPECIAUX': 
1341                                                                if (isset ($data['invalideurs'])) {
1342                                                                        $extra = $data['invalideurs'];
1343                                                                        foreach (array(
1344                                                                                'cache',
1345                                                                                'session'
1346                                                                        ) as $ki)
1347                                                                                unset($extra[$ki]);
1348                                                                }
1349                                                                break;
1350                                                        case 'INCLUSIONS' :
1351                                                                if (!isset ($data['texte']))
1352                                                                        $extra = '(html non défini)';
1353                                                                elseif (preg_match_all("/<\?php\s+echo\s+recuperer_fond\s*\(\s*'([a-z0-9_\-\.\/]+)'/", $data['texte'], $matches))
1354                                                                        $extra = $matches[1];
1355                                                                else
1356                                                                        $extra = '(aucune inclusion)';
1357                                                                break;
1358                                                        case 'MACROSESSIONS' :
1359                                                                if (!isset ($data['texte']))
1360                                                                        $extra = '(html non défini)';
1361                                                                elseif (preg_match_all("/pipelined_session_get\((['\"a-z0-9\s_\-\.\/,]+)\)/", $data['texte'], $matches))
1362                                                                        $extra = $matches[1];
1363                                                                else
1364                                                                        $extra = '(aucune macrosession)';
1365                                                                break;
1366                                                        }
1367                                                }
1368                                                if ($extra = print_contexte($extra, 1))
1369                                                        echo "<br><xmp>$extra</xmp>";
1370                                                if ($liens)     // inutilisé désormais en fait
1371                                                        echo "<small style='float:right'>$liens</small>";
1372                                        }
1373                                        echo '</td>
1374                                        <td class="td-n center">', $entry['num_hits'], '</td>
1375                                        <td class="td-n right">', $entry['mem_size'], '</td>
1376                                        <td class="td-n center">', date(DATE_FORMAT, $entry['access_time']), '</td>
1377                                        <td class="td-n center">', date(DATE_FORMAT, $entry['mtime']), '</td>
1378                                        <td class="td-n center">', date(DATE_FORMAT, $entry['creation_time']), '</td>';
1379                                       
1380                                        if ($fieldname == 'info') {
1381                                                if ($entry['ttl'])
1382                                                        echo '<td class="td-n center">' . $entry['ttl'] . ' seconds</td>';
1383                                                else
1384                                                        echo '<td class="td-n center">None</td>';
1385                                        }
1386                                        if ($entry['deletion_time']) {
1387                                               
1388                                                echo '<td class="td-last center">', date(DATE_FORMAT, $entry['deletion_time']), '</td>';
1389                                        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
1390                                               
1391                                                echo '<td class="td-last center">';
1392                                                echo '[<a href="', $MY_SELF, '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
1393                                                echo '</td>';
1394                                        } else {
1395                                                echo '<td class="td-last center"> &nbsp; </td>';
1396                                        }
1397                                        echo '</tr>';
1398                                        if ($sh == $MYREQUEST["SH"]) { // Le ZOOM sur une entrée
1399                                                echo '<tr>';
1400                                                echo '<td colspan="7">';
1401                                               
1402                                                if (isset($_GET['ZOOM']) and ($_GET['ZOOM'] == 'TEXTECOURT')) {
1403                                                        $url      = parametre_url($self, 'ZOOM', 'TEXTELONG') . "#key-$sh";
1404                                                        $menuzoom = "<a href='$url' class='menuzoom'>Voir tout le texte</a> ";
1405                                                } else {
1406                                                        $url      = parametre_url($self, 'ZOOM', 'TEXTECOURT') . "#key-$sh";
1407                                                        $menuzoom = "<a href='$url' class='menuzoom'>Voir texte abbrégé</a> ";
1408                                                }
1409                                                $url = parametre_url($self, 'SH', '') . "#key-$sh";
1410                                                $menuzoom .= "<a href='$url' class='menuzoom'>Replier</a>";
1411                                               
1412                                                if (apcu_exists($entry['info'])) {
1413                                                        $d = apcu_fetch($entry['info'], $success);
1414                                                        if ($success) {
1415                                                                echo "<p>$menuzoom</p>";
1416                                                                if (is_array($d) and (count($d) == 1) and is_serialized($d[0]))
1417                                                                        echo "<xmp>" . spipsafe_unserialize($d[0]) . "</xmp>";
1418                                                                else
1419                                                                        echo "fetch ok<br><xmp>" . print_r($d, 1) . "</xmp>";
1420                                                        } else
1421                                                                echo "fetch failed";
1422                                                } else
1423                                                        echo '(doesnt exist)';
1424                                                echo '</td>';
1425                                                echo '</tr>';
1426                                        }
1427                                        $i++;
1428                                        if ($i == $MYREQUEST['COUNT'])
1429                                                break;
1430                                }
1431                        }
1432                       
1433                } else {
1434                        echo '<tr class=tr-0><td class="center" colspan=', $cols, '><i>No data</i></td></tr>';
1435                }
1436                echo <<< EOB
1437                </tbody></table>
1438EOB;
1439               
1440                if ($list && $i < count($list)) {
1441                        echo "<a href=\"$MY_SELF", "&COUNT=0\"><i>", count($list) - $i, ' more available...</i></a>';
1442                }
1443               
1444                echo <<< EOB
1445                </div>
1446EOB;
1447                break;
1448       
1449        // -----------------------------------------------
1450        // Version check
1451        // -----------------------------------------------
1452        case OB_VERSION_CHECK:
1453                echo <<<EOB
1454                <div class="info"><h2>APCu Version Information</h2>
1455                <table cellspacing=0><tbody>
1456                <tr>
1457                <th></th>
1458                </tr>
1459EOB;
1460                if (defined('PROXY')) {
1461                        $ctxt = stream_context_create(array(
1462                                'http' => array(
1463                                        'proxy' => PROXY,
1464                                        'request_fulluri' => True
1465                                )
1466                        ));
1467                        $rss  = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss", False, $ctxt);
1468                } else {
1469                        $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss");
1470                }
1471                if (!$rss) {
1472                        echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
1473                } else {
1474                        $apcversion = phpversion('apcu');
1475                       
1476                        preg_match('!<title>APCu ([0-9.]+)</title>!', $rss, $match);
1477                        echo '<tr class="tr-0 center"><td>';
1478                        if (version_compare($apcversion, $match[1], '>=')) {
1479                                echo '<div class="ok">You are running the latest version of APCu (' . $apcversion . ')</div>';
1480                                $i = 3;
1481                        } else {
1482                                echo '<div class="failed">You are running an older version of APCu (' . $apcversion . '),
1483                                newer version ' . $match[1] . ' is available at <a href="http://pecl.php.net/package/APCu/' . $match[1] . '">
1484                                http://pecl.php.net/package/APCu/' . $match[1] . '</a>
1485                                </div>';
1486                                $i = -1;
1487                        }
1488                        echo '</td></tr>';
1489                        echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
1490                       
1491                        preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
1492                        $changelog = $match[2];
1493                       
1494                        for ($j = 2; $j + 1 < count($changelog); $j += 2) {
1495                                $v = $changelog[$j];
1496                                if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
1497                                        break;
1498                                } else if (!$i--) {
1499                                        break;
1500                                }
1501                                list($unused, $ver) = $v;
1502                                $changes = $changelog[$j + 1];
1503                                echo "<b><a href=\"http://pecl.php.net/package/APCu/$ver\">" . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . "</a></b><br><blockquote>";
1504                                echo nl2br(htmlspecialchars($changes, ENT_QUOTES, 'UTF-8')) . "</blockquote>";
1505                        }
1506                        echo '</td></tr>';
1507                }
1508                echo <<< EOB
1509                </tbody></table>
1510                </div>
1511EOB;
1512                break;
1513               
1514}
1515
1516?>
1517
1518        </div>
1519<!--
1520Based on APCGUI By R.Becker\n$VERSION
1521-->
1522</body>
1523</html>
Note: See TracBrowser for help on using the repository browser.