New PHP5 APC - version 3.0.19, using PHP5 5.2.0-8+etch11,
[php5-apc.git] / apc.php
1 <?php
2 /*
3   +----------------------------------------------------------------------+
4   | APC                                                                  |
5   +----------------------------------------------------------------------+
6   | Copyright (c) 2008 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   +----------------------------------------------------------------------+
20
21    All other licensing and usage conditions are those of the PHP Group.
22
23  */
24
25 $VERSION='$Id: apc.php,v 3.68.2.2 2008/05/11 18:57:00 rasmus Exp $';
26
27 ////////// READ OPTIONAL CONFIGURATION FILE ////////////
28 if (file_exists("apc.conf.php")) include("apc.conf.php");
29 ////////////////////////////////////////////////////////
30
31 ////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
32
33 defaults('USE_AUTHENTICATION',1);                       // Use (internal) authentication - best choice if 
34                                                                                         // no other authentication is available
35                                                                                         // If set to 0:
36                                                                                         //  There will be no further authentication. You 
37                                                                                         //  will have to handle this by yourself!
38                                                                                         // If set to 1:
39                                                                                         //  You need to change ADMIN_PASSWORD to make
40                                                                                         //  this work!
41 defaults('ADMIN_USERNAME','apc');                       // Admin Username
42 defaults('ADMIN_PASSWORD','password');          // Admin Password - CHANGE THIS TO ENABLE!!!
43
44 // (beckerr) I'm using a clear text password here, because I've no good idea how to let 
45 //           users generate a md5 or crypt password in a easy way to fill it in above
46
47 //defaults('DATE_FORMAT', "d.m.Y H:i:s");       // German
48 defaults('DATE_FORMAT', 'Y/m/d H:i:s');         // US
49
50 defaults('GRAPH_SIZE',200);                                     // Image size
51
52 ////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
53
54
55 // "define if not defined"
56 function defaults($d,$v) {
57         if (!defined($d)) define($d,$v); // or just @define(...)
58 }
59
60 // rewrite $PHP_SELF to block XSS attacks
61 //
62 $PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES) : '';
63 $time = time();
64 $host = getenv('HOSTNAME');
65 if($host) { $host = '('.$host.')'; }
66
67 // operation constants
68 define('OB_HOST_STATS',1);
69 define('OB_SYS_CACHE',2);
70 define('OB_USER_CACHE',3);
71 define('OB_SYS_CACHE_DIR',4);
72 define('OB_VERSION_CHECK',9);
73
74 // check validity of input variables
75 $vardom=array(
76         'OB'    => '/^\d+$/',                   // operational mode switch
77         'CC'    => '/^[01]$/',                  // clear cache requested
78         'DU'    => '/^.*$/',                    // Delete User Key
79         'SH'    => '/^[a-z0-9]+$/',             // shared object description
80
81         'IMG'   => '/^[123]$/',                 // image to generate
82         'LO'    => '/^1$/',                             // login requested
83
84         'COUNT' => '/^\d+$/',                   // number of line displayed in list
85         'SCOPE' => '/^[AD]$/',                  // list view scope
86         'SORT1' => '/^[AHSMCDTZ]$/',    // first sort key
87         'SORT2' => '/^[DA]$/',                  // second sort key
88         'AGGR'  => '/^\d+$/',                   // aggregation by dir level
89         'SEARCH'        => '~^[a-zA-Z0-1/_.-]*$~'                       // aggregation by dir level
90 );
91
92 // default cache mode
93 $cache_mode='opcode';
94
95 // cache scope
96 $scope_list=array(
97         'A' => 'cache_list',
98         'D' => 'deleted_list'
99 );
100
101 // handle POST and GET requests
102 if (empty($_REQUEST)) {
103         if (!empty($_GET) && !empty($_POST)) {
104                 $_REQUEST = array_merge($_GET, $_POST);
105         } else if (!empty($_GET)) {
106                 $_REQUEST = $_GET;
107         } else if (!empty($_POST)) {
108                 $_REQUEST = $_POST;
109         } else {
110                 $_REQUEST = array();
111         }
112 }
113
114 // check parameter syntax
115 foreach($vardom as $var => $dom) {
116         if (!isset($_REQUEST[$var])) {
117                 $MYREQUEST[$var]=NULL;
118         } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
119                 $MYREQUEST[$var]=$_REQUEST[$var];
120         } else {
121                 $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
122         }
123 }
124
125 // check parameter sematics
126 if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
127 if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
128 if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
129 if (empty($MYREQUEST['OB']))    $MYREQUEST['OB']=OB_HOST_STATS;
130 if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
131 if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
132
133 $MY_SELF=
134         "$PHP_SELF".
135         "?SCOPE=".$MYREQUEST['SCOPE'].
136         "&SORT1=".$MYREQUEST['SORT1'].
137         "&SORT2=".$MYREQUEST['SORT2'].
138         "&COUNT=".$MYREQUEST['COUNT'];
139 $MY_SELF_WO_SORT=
140         "$PHP_SELF".
141         "?SCOPE=".$MYREQUEST['SCOPE'].
142         "&COUNT=".$MYREQUEST['COUNT'];
143
144 // authentication needed?
145 //
146 if (!USE_AUTHENTICATION) {
147         $AUTHENTICATED=1;
148 } else {
149         $AUTHENTICATED=0;
150         if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
151
152                 if (!isset($_SERVER['PHP_AUTH_USER']) ||
153                         !isset($_SERVER['PHP_AUTH_PW']) ||
154                         $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
155                         $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
156                         Header("WWW-Authenticate: Basic realm=\"APC Login\"");
157                         Header("HTTP/1.0 401 Unauthorized");
158
159                         echo <<<EOB
160                                 <html><body>
161                                 <h1>Rejected!</h1>
162                                 <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
163                                 <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
164                                 </body></html>
165 EOB;
166                         exit;
167                         
168                 } else {
169                         $AUTHENTICATED=1;
170                 }
171         }
172 }
173         
174 // select cache mode
175 if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
176         $cache_mode='user';
177 }
178 // clear cache
179 if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
180         apc_clear_cache($cache_mode);
181 }
182
183 if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
184         apc_delete($MYREQUEST['DU']);
185 }
186
187 if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
188         echo "No cache info available.  APC does not appear to be running.";
189   exit;
190 }
191
192 $cache_user = apc_cache_info('user', 1);  
193 $mem=apc_sma_info();
194 if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
195
196 // don't cache this page
197 //
198 header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
199 header("Cache-Control: post-check=0, pre-check=0", false);
200 header("Pragma: no-cache");                                    // HTTP/1.0
201
202 function duration($ts) {
203     global $time;
204     $years = (int)((($time - $ts)/(7*86400))/52.177457);
205     $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
206     $weeks = (int)(($rem)/(7*86400));
207     $days = (int)(($rem)/86400) - $weeks*7;
208     $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
209     $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
210     $str = '';
211     if($years==1) $str .= "$years year, ";
212     if($years>1) $str .= "$years years, ";
213     if($weeks==1) $str .= "$weeks week, ";
214     if($weeks>1) $str .= "$weeks weeks, ";
215     if($days==1) $str .= "$days day,";
216     if($days>1) $str .= "$days days,";
217     if($hours == 1) $str .= " $hours hour and";
218     if($hours>1) $str .= " $hours hours and";
219     if($mins == 1) $str .= " 1 minute";
220     else $str .= " $mins minutes";
221     return $str;
222 }
223
224 // create graphics
225 //
226 function graphics_avail() {
227         return extension_loaded('gd');
228 }
229 if (isset($MYREQUEST['IMG']))
230 {
231         if (!graphics_avail()) {
232                 exit(0);
233         }
234
235         function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
236                 $r=$diameter/2;
237                 $w=deg2rad((360+$start+($end-$start)/2)%360);
238
239                 
240                 if (function_exists("imagefilledarc")) {
241                         // exists only if GD 2.0.1 is avaliable
242                         imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
243                         imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
244                         imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
245                 } else {
246                         imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
247                         imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
248                         imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
249                         imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
250                         imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
251                         imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
252                 }
253                 if ($text) {
254                         if ($placeindex>0) {
255                                 imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
256                                 imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
257                                 
258                         } else {
259                                 imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
260                         }
261                 }
262         } 
263
264         function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
265                 $r=$diameter/2;
266                 $w=deg2rad((360+$start+($end-$start)/2)%360);
267
268                 if ($placeindex>0) {
269                         imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
270                         imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
271                                 
272                 } else {
273                         imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
274                 }
275         } 
276         
277         function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
278                 global $col_black;
279                 $x1=$x+$w-1;
280                 $y1=$y+$h-1;
281
282                 imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
283                 if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
284                 else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
285                 imagerectangle($im, $x, $y1, $x1, $y, $color1);
286                 if ($text) {
287                         if ($placeindex>0) {
288                         
289                                 if ($placeindex<16)
290                                 {
291                                         $px=5;
292                                         $py=$placeindex*12+6;
293                                         imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
294                                         imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
295                                         imagestring($im,2,$px,$py-6,$text,$color1);     
296                                         
297                                 } else {
298                                         if ($placeindex<31) {
299                                                 $px=$x+40*2;
300                                                 $py=($placeindex-15)*12+6;
301                                         } else {
302                                                 $px=$x+40*2+100*intval(($placeindex-15)/15);
303                                                 $py=($placeindex%15)*12+6;
304                                         }
305                                         imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
306                                         imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
307                                         imagestring($im,2,$px+2,$py-6,$text,$color1);   
308                                 }
309                         } else {
310                                 imagestring($im,4,$x+5,$y1-16,$text,$color1);
311                         }
312                 }
313         }
314
315
316         $size = GRAPH_SIZE; // image size
317         if ($MYREQUEST['IMG']==3)
318                 $image = imagecreate(2*$size+150, $size+10);
319         else
320                 $image = imagecreate($size+50, $size+10);
321
322         $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
323         $col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
324         $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
325         $col_black = imagecolorallocate($image,   0,   0,   0);
326         imagecolortransparent($image,$col_white);
327
328         switch ($MYREQUEST['IMG']) {
329         
330         case 1:
331                 $s=$mem['num_seg']*$mem['seg_size'];
332                 $a=$mem['avail_mem'];
333                 $x=$y=$size/2;
334                 $fuzz = 0.000001;
335
336                 // This block of code creates the pie chart.  It is a lot more complex than you
337                 // would expect because we try to visualize any memory fragmentation as well.
338                 $angle_from = 0;
339                 $string_placement=array();
340                 for($i=0; $i<$mem['num_seg']; $i++) {   
341                         $ptr = 0;
342                         $free = $mem['block_lists'][$i];
343                         foreach($free as $block) {
344                                 if($block['offset']!=$ptr) {       // Used block
345                                         $angle_to = $angle_from+($block['offset']-$ptr)/$s;
346                                         if(($angle_to+$fuzz)>1) $angle_to = 1;
347                                         if( ($angle_to*360) - ($angle_from*360) >= 1) {
348                                                 fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
349                                                 if (($angle_to-$angle_from)>0.05) {
350                                                         array_push($string_placement, array($angle_from,$angle_to));
351                                                 }
352                                         }
353                                         $angle_from = $angle_to;
354                                 }
355                                 $angle_to = $angle_from+($block['size'])/$s;
356                                 if(($angle_to+$fuzz)>1) $angle_to = 1;
357                                 if( ($angle_to*360) - ($angle_from*360) >= 1) {
358                                         fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
359                                         if (($angle_to-$angle_from)>0.05) {
360                                                 array_push($string_placement, array($angle_from,$angle_to));
361                                         }
362                                 }
363                                 $angle_from = $angle_to;
364                                 $ptr = $block['offset']+$block['size'];
365                         }
366                         if ($ptr < $mem['seg_size']) { // memory at the end 
367                                 $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
368                                 if(($angle_to+$fuzz)>1) $angle_to = 1;
369                                 fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
370                                 if (($angle_to-$angle_from)>0.05) {
371                                         array_push($string_placement, array($angle_from,$angle_to));
372                                 }
373                         }
374                 }
375                 foreach ($string_placement as $angle) {
376                         text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
377                 }
378                 break;
379                 
380         case 2: 
381                 $s=$cache['num_hits']+$cache['num_misses'];
382                 $a=$cache['num_hits'];
383                 
384                 fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
385                 fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
386                 break;
387                 
388         case 3:
389                 $s=$mem['num_seg']*$mem['seg_size'];
390                 $a=$mem['avail_mem'];
391                 $x=130;
392                 $y=1;
393                 $j=1;
394
395                 // This block of code creates the bar chart.  It is a lot more complex than you
396                 // would expect because we try to visualize any memory fragmentation as well.
397                 for($i=0; $i<$mem['num_seg']; $i++) {   
398                         $ptr = 0;
399                         $free = $mem['block_lists'][$i];
400                         foreach($free as $block) {
401                                 if($block['offset']!=$ptr) {       // Used block
402                                         $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
403                                         if ($h>0) {
404                                                 $j++;
405                                                 if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
406                                                 else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
407                                         }
408                                         $y+=$h;
409                                 }
410                                 $h=(GRAPH_SIZE-5)*($block['size'])/$s;
411                                 if ($h>0) {
412                                         $j++;
413                                         if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
414                                         else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
415                                 }
416                                 $y+=$h;
417                                 $ptr = $block['offset']+$block['size'];
418                         }
419                         if ($ptr < $mem['seg_size']) { // memory at the end 
420                                 $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
421                                 if ($h > 0) {
422                                         fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
423                                 }
424                         }
425                 }
426                 break;
427         case 4: 
428                 $s=$cache['num_hits']+$cache['num_misses'];
429                 $a=$cache['num_hits'];
430                         
431                 fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
432                 fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
433                 break;
434         
435         }
436         header("Content-type: image/png");
437         imagepng($image);
438         exit;
439 }
440
441 // pretty printer for byte values
442 //
443 function bsize($s) {
444         foreach (array('','K','M','G') as $i => $k) {
445                 if ($s < 1024) break;
446                 $s/=1024;
447         }
448         return sprintf("%5.1f %sBytes",$s,$k);
449 }
450
451 // sortable table header in "scripts for this host" view
452 function sortheader($key,$name,$extra='') {
453         global $MYREQUEST, $MY_SELF_WO_SORT;
454         
455         if ($MYREQUEST['SORT1']==$key) {
456                 $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
457         }
458         return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
459
460 }
461
462 // create menu entry 
463 function menu_entry($ob,$title) {
464         global $MYREQUEST,$MY_SELF;
465         if ($MYREQUEST['OB']!=$ob) {
466                 return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
467         } else if (empty($MYREQUEST['SH'])) {
468                 return "<li><span class=active>$title</span></li>";
469         } else {
470                 return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
471         }
472 }
473
474 function put_login_link($s="Login")
475 {
476         global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
477         // needs ADMIN_PASSWORD to be changed!
478         //
479         if (!USE_AUTHENTICATION) {
480                 return;
481         } else if (ADMIN_PASSWORD=='password')
482         {
483                 print <<<EOB
484                         <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>
485 EOB;
486         } else if ($AUTHENTICATED) {
487                 print <<<EOB
488                         '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
489 EOB;
490         } else{
491                 print <<<EOB
492                         <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
493 EOB;
494         }
495 }
496
497
498 ?>
499 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
500 <html>
501 <head><title>APC INFO <?php echo $host ?></title>
502 <style><!--
503 body { background:white; font-size:100.01%; margin:0; padding:0; }
504 body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
505 * html body   {font-size:0.8em}
506 * html p      {font-size:0.8em}
507 * html td     {font-size:0.8em}
508 * html th     {font-size:0.8em}
509 * html input  {font-size:0.8em}
510 * html submit {font-size:0.8em}
511 td { vertical-align:top }
512 a { color:black; font-weight:none; text-decoration:none; }
513 a:hover { text-decoration:underline; }
514 div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
515
516
517 div.head div.login {
518         position:absolute;
519         right: 1em;
520         top: 1.2em;
521         color:white;
522         width:6em;
523         }
524 div.head div.login a {
525         position:absolute;
526         right: 0em;
527         background:rgb(119,123,180);
528         border:solid rgb(102,102,153) 2px;
529         color:white;
530         font-weight:bold;
531         padding:0.1em 0.5em 0.1em 0.5em;
532         text-decoration:none;
533         }
534 div.head div.login a:hover {
535         background:rgb(193,193,244);
536         }
537
538 h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
539 * html h1.apc { margin-bottom:-7px; }
540 h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
541 h1.apc div.logo span.logo {
542         background:rgb(119,123,180);
543         color:black;
544         border-right: solid black 1px;
545         border-bottom: solid black 1px;
546         font-style:italic;
547         font-size:1em;
548         padding-left:1.2em;
549         padding-right:1.2em;
550         text-align:right;
551         }
552 h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
553 h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
554 h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
555 hr.apc {
556         background:white;
557         border-bottom:solid rgb(102,102,153) 1px;
558         border-style:none;
559         border-top:solid rgb(102,102,153) 10px;
560         height:12px;
561         margin:0;
562         margin-top:1px;
563         padding:0;
564 }
565
566 ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
567 ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
568 ol.menu a {
569         background:rgb(153,153,204);
570         border:solid rgb(102,102,153) 2px;
571         color:white;
572         font-weight:bold;
573         margin-right:0em;
574         padding:0.1em 0.5em 0.1em 0.5em;
575         text-decoration:none;
576         margin-left: 5px;
577         }
578 ol.menu a.child_active {
579         background:rgb(153,153,204);
580         border:solid rgb(102,102,153) 2px;
581         color:white;
582         font-weight:bold;
583         margin-right:0em;
584         padding:0.1em 0.5em 0.1em 0.5em;
585         text-decoration:none;
586         border-left: solid black 5px;
587         margin-left: 0px;
588         }
589 ol.menu span.active {
590         background:rgb(153,153,204);
591         border:solid rgb(102,102,153) 2px;
592         color:black;
593         font-weight:bold;
594         margin-right:0em;
595         padding:0.1em 0.5em 0.1em 0.5em;
596         text-decoration:none;
597         border-left: solid black 5px;
598         }
599 ol.menu span.inactive {
600         background:rgb(193,193,244);
601         border:solid rgb(182,182,233) 2px;
602         color:white;
603         font-weight:bold;
604         margin-right:0em;
605         padding:0.1em 0.5em 0.1em 0.5em;
606         text-decoration:none;
607         margin-left: 5px;
608         }
609 ol.menu a:hover {
610         background:rgb(193,193,244);
611         text-decoration:none;
612         }
613         
614         
615 div.info {
616         background:rgb(204,204,204);
617         border:solid rgb(204,204,204) 1px;
618         margin-bottom:1em;
619         }
620 div.info h2 {
621         background:rgb(204,204,204);
622         color:black;
623         font-size:1em;
624         margin:0;
625         padding:0.1em 1em 0.1em 1em;
626         }
627 div.info table {
628         border:solid rgb(204,204,204) 1px;
629         border-spacing:0;
630         width:100%;
631         }
632 div.info table th {
633         background:rgb(204,204,204);
634         color:white;
635         margin:0;
636         padding:0.1em 1em 0.1em 1em;
637         }
638 div.info table th a.sortable { color:black; }
639 div.info table tr.tr-0 { background:rgb(238,238,238); }
640 div.info table tr.tr-1 { background:rgb(221,221,221); }
641 div.info table td { padding:0.3em 1em 0.3em 1em; }
642 div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
643 div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
644 div.info table td h3 {
645         color:black;
646         font-size:1.1em;
647         margin-left:-0.3em;
648         }
649
650 div.graph { margin-bottom:1em }
651 div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
652 div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
653 div.graph table td.td-0 { background:rgb(238,238,238); }
654 div.graph table td.td-1 { background:rgb(221,221,221); }
655 div.graph table td { padding:0.2em 1em 0.4em 1em; }
656
657 div.div1,div.div2 { margin-bottom:1em; width:35em; }
658 div.div3 { position:absolute; left:40em; top:1em; width:580px; }
659 //div.div3 { position:absolute; left:37em; top:1em; right:1em; }
660
661 div.sorting { margin:1.5em 0em 1.5em 2em }
662 .center { text-align:center }
663 .aright { position:absolute;right:1em }
664 .right { text-align:right }
665 .ok { color:rgb(0,200,0); font-weight:bold}
666 .failed { color:rgb(200,0,0); font-weight:bold}
667
668 span.box {
669         border: black solid 1px;
670         border-right:solid black 2px;
671         border-bottom:solid black 2px;
672         padding:0 0.5em 0 0.5em;
673         margin-right:1em;
674 }
675 span.green { background:#60F060; padding:0 0.5em 0 0.5em}
676 span.red { background:#D06030; padding:0 0.5em 0 0.5em }
677
678 div.authneeded {
679         background:rgb(238,238,238);
680         border:solid rgb(204,204,204) 1px;
681         color:rgb(200,0,0);
682         font-size:1.2em;
683         font-weight:bold;
684         padding:2em;
685         text-align:center;
686         }
687         
688 input {
689         background:rgb(153,153,204);
690         border:solid rgb(102,102,153) 2px;
691         color:white;
692         font-weight:bold;
693         margin-right:1em;
694         padding:0.1em 0.5em 0.1em 0.5em;
695         }
696 //-->
697 </style>
698 </head>
699 <body>
700 <div class="head">
701         <h1 class="apc">
702                 <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
703                 <div class="nameinfo">Opcode Cache</div>
704         </h1>
705         <div class="login">
706         <?php put_login_link(); ?>
707         </div>
708         <hr class="apc">
709 </div>
710 <?php
711
712
713 // Display main Menu
714 echo <<<EOB
715         <ol class=menu>
716         <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
717 EOB;
718 echo
719         menu_entry(1,'View Host Stats'),
720         menu_entry(2,'System Cache Entries');
721 if ($AUTHENTICATED) {
722         echo menu_entry(4,'Per-Directory Entries');
723 }
724 echo
725         menu_entry(3,'User Cache Entries'),
726         menu_entry(9,'Version Check');
727         
728 if ($AUTHENTICATED) {
729         echo <<<EOB
730                 <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
731 EOB;
732 }
733 echo <<<EOB
734         </ol>
735 EOB;
736
737
738 // CONTENT
739 echo <<<EOB
740         <div class=content>
741 EOB;
742
743 // MAIN SWITCH STATEMENT 
744
745 switch ($MYREQUEST['OB']) {
746
747
748
749
750
751 // -----------------------------------------------
752 // Host Stats
753 // -----------------------------------------------
754 case OB_HOST_STATS:
755         $mem_size = $mem['num_seg']*$mem['seg_size'];
756         $mem_avail= $mem['avail_mem'];
757         $mem_used = $mem_size-$mem_avail;
758         $seg_size = bsize($mem['seg_size']);
759         $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
760         $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
761         $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
762         $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
763         $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
764         $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
765         $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
766         $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
767         $apcversion = phpversion('apc');
768         $phpversion = phpversion();
769         $number_files = $cache['num_entries']; 
770     $size_files = bsize($cache['mem_size']);
771         $number_vars = $cache_user['num_entries'];
772     $size_vars = bsize($cache_user['mem_size']);
773         $i=0;
774         echo <<< EOB
775                 <div class="info div1"><h2>General Cache Information</h2>
776                 <table cellspacing=0><tbody>
777                 <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
778                 <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
779 EOB;
780
781         if(!empty($_SERVER['SERVER_NAME']))
782                 echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
783         if(!empty($_SERVER['SERVER_SOFTWARE']))
784                 echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
785
786         echo <<<EOB
787                 <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
788     <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
789     </td></tr>
790 EOB;
791         echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
792         echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
793         echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
794         echo <<<EOB
795                 </tbody></table>
796                 </div>
797
798                 <div class="info div1"><h2>File Cache Information</h2>
799                 <table cellspacing=0><tbody>
800                 <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
801                 <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
802                 <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
803                 <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
804                 <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
805                 <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
806                 <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
807                 <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
808                 </tbody></table>
809                 </div>
810
811                 <div class="info div1"><h2>User Cache Information</h2>
812                 <table cellspacing=0><tbody>
813     <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
814                 <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
815                 <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
816                 <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
817                 <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
818                 <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
819                 <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
820                 <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
821
822                 </tbody></table>
823                 </div>
824
825                 <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
826 EOB;
827
828         $j = 0;
829         foreach (ini_get_all('apc') as $k => $v) {
830                 echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
831                 $j = 1 - $j;
832         }
833
834         if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
835                 $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
836         else
837                 $mem_note = "Memory Usage";
838
839         echo <<< EOB
840                 </tbody></table>
841                 </div>
842
843                 <div class="graph div3"><h2>Host Status Diagrams</h2>
844                 <table cellspacing=0><tbody>
845 EOB;
846         $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
847         echo <<<EOB
848                 <tr>
849                 <td class=td-0>$mem_note</td>
850                 <td class=td-1>Hits &amp; Misses</td>
851                 </tr>
852 EOB;
853
854         echo
855                 graphics_avail() ? 
856                           '<tr>'.
857                           "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
858                           "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
859                         : "",
860                 '<tr>',
861                 '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
862                 '<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",
863                 '</tr>',
864                 '<tr>',
865                 '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
866                 '<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";
867         echo <<< EOB
868                 </tr>
869                 </tbody></table>
870
871                 <br/>
872                 <h2>Detailed Memory Usage and Fragmentation</h2>
873                 <table cellspacing=0><tbody>
874                 <tr>
875                 <td class=td-0 colspan=2><br/>
876 EOB;
877
878         // Fragementation: (freeseg - 1) / total_seg
879         $nseg = $freeseg = $fragsize = $freetotal = 0;
880         for($i=0; $i<$mem['num_seg']; $i++) {
881                 $ptr = 0;
882                 foreach($mem['block_lists'][$i] as $block) {
883                         if ($block['offset'] != $ptr) {
884                                 ++$nseg;
885                         }
886                         $ptr = $block['offset'] + $block['size'];
887                         /* Only consider blocks <5M for the fragmentation % */
888                         if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
889                         $freetotal+=$block['size'];
890                 }
891                 $freeseg += count($mem['block_lists'][$i]);
892         }
893         
894         if ($freeseg > 1) {
895                 $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
896         } else {
897                 $frag = "0%";
898         }
899
900         if (graphics_avail()) {
901                 $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
902                 echo <<<EOB
903                         <img alt="" $size src="$PHP_SELF?IMG=3&$time">
904 EOB;
905         }
906         echo <<<EOB
907                 </br>Fragmentation: $frag
908                 </td>
909                 </tr>
910 EOB;
911         if(isset($mem['adist'])) {
912           foreach($mem['adist'] as $i=>$v) {
913             $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
914             if($i==0) $range = "1";
915             else $range = "$cur - $nxt";
916             echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
917           }
918         }
919         echo <<<EOB
920                 </tbody></table>
921                 </div>
922 EOB;
923                 
924         break;
925
926
927 // -----------------------------------------------
928 // User Cache Entries
929 // -----------------------------------------------
930 case OB_USER_CACHE:
931         if (!$AUTHENTICATED) {
932     echo '<div class="error">You need to login to see the user values here!<br/>&nbsp;<br/>';
933                 put_login_link("Login now!");
934                 echo '</div>';
935                 break;
936         }
937         $fieldname='info';
938         $fieldheading='User Entry Label';
939         $fieldkey='info';
940
941 // -----------------------------------------------
942 // System Cache Entries         
943 // -----------------------------------------------
944 case OB_SYS_CACHE:      
945         if (!isset($fieldname))
946         {
947                 $fieldname='filename';
948                 $fieldheading='Script Filename';
949                 if(ini_get("apc.stat")) $fieldkey='inode';
950                 else $fieldkey='filename'; 
951         }
952         if (!empty($MYREQUEST['SH']))
953         {
954                 echo <<< EOB
955                         <div class="info"><table cellspacing=0><tbody>
956                         <tr><th>Attribute</th><th>Value</th></tr>
957 EOB;
958
959                 $m=0;
960                 foreach($scope_list as $j => $list) {
961                         foreach($cache[$list] as $i => $entry) {
962                                 if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
963                                 foreach($entry as $k => $value) {
964                                         if (!$AUTHENTICATED) {
965                                                 // hide all path entries if not logged in
966                                                 $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
967                                         }
968
969                                         if ($k == "num_hits") {
970                                                 $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
971                                         }
972                                         if ($k == 'deletion_time') {
973                                                 if(!$entry['deletion_time']) $value = "None";
974                                         }
975                                         echo
976                                                 "<tr class=tr-$m>",
977                                                 "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
978                                                 "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
979                                                 "</tr>";
980                                         $m=1-$m;
981                                 }
982                                 if($fieldkey=='info') {
983                                         echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
984                                         $output = var_export(apc_fetch($entry[$fieldkey]),true);
985                                         echo htmlspecialchars($output);
986                                         echo "</pre></td></tr>\n";
987                                 }
988                                 break;
989                         }
990                 }
991
992                 echo <<<EOB
993                         </tbody></table>
994                         </div>
995 EOB;
996                 break;
997         }
998
999         $cols=6;
1000         echo <<<EOB
1001                 <div class=sorting><form>Scope:
1002                 <input type=hidden name=OB value={$MYREQUEST['OB']}>
1003                 <select name=SCOPE>
1004 EOB;
1005         echo 
1006                 "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
1007                 "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
1008                 "</select>",
1009                 ", Sorting:<select name=SORT1>",
1010                 "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
1011                 "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
1012                 "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
1013                 "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
1014                 "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
1015                 "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
1016                 "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
1017         if($fieldname=='info') echo
1018                 "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
1019         echo 
1020                 '</select>',
1021                 '<select name=SORT2>',
1022                 '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
1023                 '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
1024                 '</select>',
1025                 '<select name=COUNT onChange="form.submit()">',
1026                 '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
1027                 '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
1028                 '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
1029                 '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
1030                 '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
1031                 '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
1032                 '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
1033                 '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
1034                 '</select>',
1035     '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
1036                 '&nbsp;<input type=submit value="GO!">',
1037                 '</form></div>';
1038
1039   if (isset($MYREQUEST['SEARCH'])) {
1040    // Don't use preg_quote because we want the user to be able to specify a
1041    // regular expression subpattern.
1042    $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i';
1043    if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
1044      echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
1045      break;
1046    }
1047   }
1048
1049   echo
1050                 '<div class="info"><table cellspacing=0><tbody>',
1051                 '<tr>',
1052                 '<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
1053                 '<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
1054                 '<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
1055                 '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
1056                 '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
1057                 '<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
1058
1059         if($fieldname=='info') {
1060                 $cols+=2;
1061                  echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
1062         }
1063         echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
1064
1065         // builds list with alpha numeric sortable keys
1066         //
1067         $list = array();
1068         foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
1069                 switch($MYREQUEST['SORT1']) {
1070                         case 'A': $k=sprintf('%015d-',$entry['access_time']);   break;
1071                         case 'H': $k=sprintf('%015d-',$entry['num_hits']);              break;
1072                         case 'Z': $k=sprintf('%015d-',$entry['mem_size']);              break;
1073                         case 'M': $k=sprintf('%015d-',$entry['mtime']);                 break;
1074                         case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
1075                         case 'T': $k=sprintf('%015d-',$entry['ttl']);                   break;
1076                         case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
1077                         case 'S': $k='';                                                                                break;
1078                 }
1079                 if (!$AUTHENTICATED) {
1080                         // hide all path entries if not logged in
1081                         $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
1082                 } else {
1083                         $list[$k.$entry[$fieldname]]=$entry;
1084                 }
1085         }
1086
1087         if ($list) {
1088                 
1089                 // sort list
1090                 //
1091                 switch ($MYREQUEST['SORT2']) {
1092                         case "A":       krsort($list);  break;
1093                         case "D":       ksort($list);   break;
1094                 }
1095                 
1096                 // output list
1097                 $i=0;
1098                 foreach($list as $k => $entry) {
1099       if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {  
1100         echo
1101           '<tr class=tr-',$i%2,'>',
1102           "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
1103           '<td class="td-n center">',$entry['num_hits'],'</td>',
1104           '<td class="td-n right">',$entry['mem_size'],'</td>',
1105           '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
1106           '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
1107           '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
1108
1109         if($fieldname=='info') {
1110           if($entry['ttl'])
1111             echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
1112           else
1113             echo '<td class="td-n center">None</td>';
1114         }
1115         if ($entry['deletion_time']) {
1116
1117           echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
1118         } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
1119
1120           echo '<td class="td-last center">';
1121           echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
1122           echo '</td>';
1123         } else {
1124           echo '<td class="td-last center"> &nbsp; </td>';
1125         }
1126         echo '</tr>';
1127         $i++;
1128         if ($i == $MYREQUEST['COUNT'])
1129           break;
1130       }
1131                 }
1132                 
1133         } else {
1134                 echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
1135         }
1136         echo <<< EOB
1137                 </tbody></table>
1138 EOB;
1139
1140         if ($list && $i < count($list)) {
1141                 echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
1142         }
1143
1144         echo <<< EOB
1145                 </div>
1146 EOB;
1147         break;
1148
1149
1150 // -----------------------------------------------
1151 // Per-Directory System Cache Entries
1152 // -----------------------------------------------
1153 case OB_SYS_CACHE_DIR:  
1154         if (!$AUTHENTICATED) {
1155                 break;
1156         }
1157
1158         echo <<<EOB
1159                 <div class=sorting><form>Scope:
1160                 <input type=hidden name=OB value={$MYREQUEST['OB']}>
1161                 <select name=SCOPE>
1162 EOB;
1163         echo 
1164                 "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
1165                 "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
1166                 "</select>",
1167                 ", Sorting:<select name=SORT1>",
1168                 "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
1169                 "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
1170                 "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
1171                 "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
1172                 "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
1173                 "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
1174                 '</select>',
1175                 '<select name=SORT2>',
1176                 '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
1177                 '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
1178                 '</select>',
1179                 '<select name=COUNT onChange="form.submit()">',
1180                 '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
1181                 '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
1182                 '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
1183                 '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
1184                 '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
1185                 '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
1186                 '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
1187                 '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
1188                 '</select>',
1189                 ", Group By Dir Level:<select name=AGGR>",
1190                 "<option value='' selected>None</option>";
1191                 for ($i = 1; $i < 10; $i++)
1192                         echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
1193                 echo '</select>',
1194                 '&nbsp;<input type=submit value="GO!">',
1195                 '</form></div>',
1196
1197                 '<div class="info"><table cellspacing=0><tbody>',
1198                 '<tr>',
1199                 '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
1200                 '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
1201                 '<th>',sortheader('H','Total Hits',     "&OB=".$MYREQUEST['OB']),'</th>',
1202                 '<th>',sortheader('Z','Total Size',     "&OB=".$MYREQUEST['OB']),'</th>',
1203                 '<th>',sortheader('C','Avg. Hits',      "&OB=".$MYREQUEST['OB']),'</th>',
1204                 '<th>',sortheader('A','Avg. Size',      "&OB=".$MYREQUEST['OB']),'</th>',
1205                 '</tr>';
1206
1207         // builds list with alpha numeric sortable keys
1208         //
1209         $tmp = $list = array();
1210         foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
1211                 $n = dirname($entry['filename']);
1212                 if ($MYREQUEST['AGGR'] > 0) {
1213                         $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
1214                 }
1215                 if (!isset($tmp[$n])) {
1216                         $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
1217                 }
1218                 $tmp[$n]['hits'] += $entry['num_hits'];
1219                 $tmp[$n]['size'] += $entry['mem_size'];
1220                 ++$tmp[$n]['ents'];
1221         }
1222
1223         foreach ($tmp as $k => $v) {
1224                 switch($MYREQUEST['SORT1']) {
1225                         case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
1226                         case 'T': $kn=sprintf('%015d-',$v['ents']);             break;
1227                         case 'H': $kn=sprintf('%015d-',$v['hits']);             break;
1228                         case 'Z': $kn=sprintf('%015d-',$v['size']);             break;
1229                         case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
1230                         case 'S': $kn = $k;                                     break;
1231                 }
1232                 $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
1233         }
1234
1235         if ($list) {
1236                 
1237                 // sort list
1238                 //
1239                 switch ($MYREQUEST['SORT2']) {
1240                         case "A":       krsort($list);  break;
1241                         case "D":       ksort($list);   break;
1242                 }
1243                 
1244                 // output list
1245                 $i = 0;
1246                 foreach($list as $entry) {
1247                         echo
1248                                 '<tr class=tr-',$i%2,'>',
1249                                 "<td class=td-0>",$entry[0],'</a></td>',
1250                                 '<td class="td-n center">',$entry[1],'</td>',
1251                                 '<td class="td-n center">',$entry[2],'</td>',
1252                                 '<td class="td-n center">',$entry[3],'</td>',
1253                                 '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
1254                                 '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
1255                                 '</tr>';
1256
1257                         if (++$i == $MYREQUEST['COUNT']) break;
1258                 }
1259                 
1260         } else {
1261                 echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
1262         }
1263         echo <<< EOB
1264                 </tbody></table>
1265 EOB;
1266
1267         if ($list && $i < count($list)) {
1268                 echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
1269         }
1270
1271         echo <<< EOB
1272                 </div>
1273 EOB;
1274         break;
1275
1276 // -----------------------------------------------
1277 // Version check
1278 // -----------------------------------------------
1279 case OB_VERSION_CHECK:
1280         echo <<<EOB
1281                 <div class="info"><h2>APC Version Information</h2>
1282                 <table cellspacing=0><tbody>
1283                 <tr>
1284                 <th></th>
1285                 </tr>
1286 EOB;
1287
1288         $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
1289         if (!$rss) {
1290                 echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
1291         } else {
1292                 $apcversion = phpversion('apc');
1293
1294                 preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
1295                 echo '<tr class="tr-0 center"><td>';
1296                 if (version_compare($apcversion, $match[1], '>=')) {
1297                         echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
1298                         $i = 3;
1299                 } else {
1300                         echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
1301                                 newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
1302                                 http://pecl.php.net/package/APC/'.$match[1].'</a>
1303                                 </div>';
1304                         $i = -1;
1305                 }
1306                 echo '</td></tr>';
1307                 echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
1308
1309                 preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
1310                 next($match[2]); next($match[2]);
1311
1312                 while (list(,$v) = each($match[2])) {
1313                         list(,$ver) = explode(' ', $v, 2);
1314                         if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
1315                                 break;
1316                         } else if (!$i--) {
1317                                 break;
1318                         }
1319                         echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
1320                         echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
1321                         next($match[2]);
1322                 }
1323                 echo '</td></tr>';
1324         }
1325         echo <<< EOB
1326                 </tbody></table>
1327                 </div>
1328 EOB;
1329         break;
1330
1331 }
1332
1333 echo <<< EOB
1334         </div>
1335 EOB;
1336
1337 ?>
1338
1339 <!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
1340 </body>
1341 </html>