root/eaccelerator/branches/new-cache/control.php

Revision 330, 22.4 kB (checked in by hans, 1 year ago)

* Changed crash handler error message format to Apache-style error log format as suggested in ticket #217
* Fixed ticket #274
* Performance: eliminated a bunch of time() syscalls
* Performance: eliminated calls to eaccelerator_gc when not build with either session, shm or user cache functionality (which are all off by default)
* Disable eaccelerator_list_keys function when not build with either session, shm or user cache functionality (which are all off by default)
* Disable 'User Cache' tab in control panel when not build with either session, shm or user cache functionality (which are all off by default)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /*
3        +-----------------------------------------------------------------------+
4        | eAccelerator control panel                                               |
5        +-----------------------------------------------------------------------+
6        | Copyright (c) 2004-2007 eAccelerator                                     |
7     | http://eaccelerator.net                                                  |
8        +-----------------------------------------------------------------------+
9        | This source file is subject to version 3.0 of the PHP license,           |
10     | that is bundled with this package in the file LICENSE, and is            |
11     | available through the world-wide-web at the following url:               |
12     | http://www.php.net/license/3_0.txt.                                      |
13     | If you did not receive a copy of the PHP license and are unable to       |
14     | obtain it through the world-wide-web, please send a note to              |
15     | license@php.net so we can mail you a copy immediately.                 |
16     +-----------------------------------------------------------------------+
17 */
18
19 /*** CONFIG ***/
20 $auth = false;        // Set to false to disable authentication
21 $user = "admin";
22 $pw = "eAccelerator";
23
24 $npp = 50;        // Number of records per page (script / key cache listings)
25
26 /*** TODO for API / reporting / this script:
27      + want script ttl from API
28      + would be cool to have init_time for scripts (time of caching) - could then get hit rates etc.
29      + count hits on user keys
30      + colon bug in eaccelerator_list_keys()
31      + might be better if usercache ttl was returned as absolute time even if expired
32 */
33
34 // Inline media
35 if (isset($_GET['img']) && $_GET['img']) {
36     $img = strtolower($_GET['img']);
37     $imgs['dnarr'][0] = 199;
38     $imgs['dnarr'][1] = 'H4sIAAAAAAAAA3P3dLOwTORlEGBoZ2BYsP3Y0t0nlu85ueHQ2U1Hzu86efnguetHL968cPPBtbuPbzx4+vTV24+fv3768u3nr9+/f//59+/f////GUbBKBgWQPEnCzMDgyCDDogDyhMMHP4MyhwyHhsWHGzmENaKOSHAyMDAKMWTI/BAkYmDTU6oQuAhY2M7m4JLgcGDh40c7HJ8BQaBBw4z8bMaaOx4sPAsK7voDZ8GAadTzEqSXLJWBgoM1gBhknrUcgMAAA==';
39     $imgs['uparr'][0] = 201;
40     $imgs['uparr'][1] = 'H4sIAAAAAAAAA3P3dLOwTORlEGBoZ2BYsP3Y0t0nlu85ueHQ2U1Hzu86efnguetHL968cPPBtbuPbzx4+vTV24+fv3768u3nr9+/f//59+/f////GUbBKBgWQPEnCzMDgyCDDogDyhMMHIEMyhwyHhsWHGzmENaKOTFBoYWZgc/BYQVDw1EWdvGIOzsWJDAzinFHiBxIWNDMKMbv0sCR0NDMIcATofJB4RAzkxivg0OCoUNzIy9ThMuFDRqHGxisAZtUvS50AwAA';
41
42     if (!$imgs[$img] || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false)
43         exit();
44
45     header("Expires: ".gmdate("D, d M Y H:i:s", time()+(86400*30))." GMT");
46     header("Last-Modified: ".gmdate("D, d M Y H:i:s", time())." GMT");
47     header('Accept-Ranges: bytes');
48     header('Content-Length: '.$imgs[$img][0]);
49     header('Content-Type: image/gif');
50     header('Content-Encoding: gzip');
51
52     echo base64_decode($imgs[$img][1]);
53     exit();
54 }
55
56 // Authenticate before proceeding
57 if ($auth && (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) ||
58         $_SERVER['PHP_AUTH_USER'] != $user || $_SERVER['PHP_AUTH_PW'] != $pw)) {
59     header('WWW-Authenticate: Basic realm="eAccelerator control panel"');
60     header('HTTP/1.0 401 Unauthorized');
61     exit;
62 }
63
64 $sec = isset($_GET['sec']) ? (int)$_GET['sec'] : 0;
65
66 // No-cache headers
67 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
68 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
69 header("Cache-Control: no-store, no-cache, must-revalidate");
70 header("Cache-Control: post-check=0, pre-check=0", false);
71 header("Pragma: no-cache");
72
73 function print_footer() {
74     global $info;
75 ?>
76 </div>
77 <div class="footer">
78 <?php
79 if (is_array($info)) {
80 ?>
81 <br/><br/>
82     <hr style="width:500px; color: #cdcdcd" noshade="noshade" size="1" />
83     <strong>Created by the eAccelerator team &ndash; <a href="http://eaccelerator.net">http://eaccelerator.net</a></strong><br /><br />
84     eAccelerator <?php echo $info['version']; ?> [shm:<?php echo $info['shm_type']?> sem:<?php echo $info['sem_type']; ?>]<br />
85     PHP <?php echo phpversion();?> [ZE <?php echo zend_version(); ?>]<br />
86     Using <?php echo php_sapi_name();?> on <?php echo php_uname(); ?><br />
87 <?php
88 }
89 ?>
90 </div>
91 </body>
92 </html>
93 <?php
94 }
95
96 if (!function_exists('eaccelerator_info')) {
97     die('eAccelerator isn\'t installed or isn\'t compiled with info support!');
98 }
99
100 // formats sizes
101 function format_size ($x) {
102     $a = array('bytes', 'kb', 'mb', 'gb');
103     $i = 0;
104     while ($x >= 1024) {
105         $i++;
106         $x = $x / 1024;
107     }
108     return number_format($x, ($i > 0)?2:0, '.', ',').' '.$a[$i];
109 }
110
111 // Generates a simple & colourful horizontal bar graph. $x:$y is used:free
112 function space_graph ($x, $y) {
113     $colr = 183; $colg = 225; $colb = 149;    // #B7E195
114
115     $colr = base_convert($colr + floor(($x/$y)*(50+exp($x*3/$y))), 10, 16);
116     $colg = base_convert($colg - floor(($x/$y)*(100+exp($x*4/$y))), 10, 16);
117     $colb = base_convert($colb - floor(($x/$y)*(70+exp($x*4/$y))), 10, 16);
118
119     $s = '<table class="hgraph"><tr>';
120     $s .= '<td class="hgraph_pri" style="width:'.floor(($x/$y)*100).'%">&nbsp;</td>';
121     $s .= '<td class="hgraph_sec" style="background-color: #'.$colr.$colg.$colb.'; width:'.ceil(100 - ($x/$y)*100).'%">&nbsp;</td></tr></table>';
122     return $s;
123 }
124
125 // Messy algorithm to generate neat page selectors
126 function pageselstr ($pg, $pgs) {
127     $pg += 1;
128     $st = max(1, $pg - 2) - max(0, 2 - ($pgs - $pg));
129     $nd = $pg + 2 + max(0, 3 - $pg);
130     $d = $st - 1 - 1;
131     if (abs($nd - $pg) > 2) $sp[] = $nd - 2;
132     if (abs($pg - $st) > 2) $sp[] = $st + 2;
133     if (($d-2)/3 >= 2) {
134         $sp[] = (ceil($d/3)+1);
135         $sp[] = (ceil($d/3)*2+1);
136     }
137     elseif (($d-1)/2 > 0) $sp[] = (ceil($d/2)+1);
138     $d = $pgs - $nd - 1;
139     if (($d-2)/3 >= 2) {
140         $sp[] = (ceil($d/3)+$nd);
141         $sp[] = (ceil($d/3)*2+$nd);
142     }
143     elseif (($d-1)/2 > 0) $sp[] = (ceil($d/2)+$nd);
144     $sp[] = $st;$sp[] = $nd;$sp[] = $pg;$sp[] = 1;$sp[] = $pgs;
145     $lp = 1;
146     $pgstr = 'Page: ';
147     if ($pgs < 1) $pgstr .= '-';
148     for ($i = 1; $i <= $pgs; $i++) {
149         if (in_array($i, $sp)) {
150             if ($i - $lp <= 2 && $i > 2 && !in_array($i-1, $sp)) $pgstr .= '<a href="'.$_SERVER['PHP_SELF'].'?'.qstring_update(array('pg' => $i-2)).'">'.($i-1).'</a> ';
151             if ($i - $lp > 2) $pgstr .= '..';
152             if ($i == $pg) $pgstr .= ' ['.$i.'] ';
153             else {
154                 $pgstr .= ' <a href="'.$_SERVER['PHP_SELF'].'?'.qstring_update(array('pg' => $i-1)).'">'.$i.'</a> ';
155             }
156             $lp = $i;
157         }
158     }
159     return $pgstr;
160 }
161
162 // Returns qstring with updated key / value pairs.
163 function qstring_update ($arr) {
164     $qs = '';
165     $combo = array_merge($_GET, $arr);
166     foreach ($combo as $a => $b) {
167         if ($qs) $qs .= '&';
168         $qs .= urlencode($a).'='.urlencode($b);
169     }
170     return $qs;
171 }
172
173 // Returns standard column headers for the lists
174 function colheadstr ($nme, $id) {
175     $cursrt = isset($_GET['ordby']) ? $_GET['ordby'] : 0;
176     $srtdir = isset($_GET['dir']) ? $_GET['dir'] : "";
177     return '<a href="'.$_SERVER['PHP_SELF'].'?'.qstring_update(array('ordby' => $id, 'dir' => ($cursrt == $id)?1-$srtdir:0)).'">'.$nme.'&nbsp;'.(($cursrt == $id)?'<img src="'.$_SERVER['PHP_SELF'].'?img='.(($srtdir)?'dnarr':'uparr').'" width="13" height="16" border="0" alt="'.(($srtdir)?'v':'^').'"/>':'');
178 }
179
180 // Array sorting callback function
181 function arrsort ($a, $b) {
182     global $ordby, $ordbystr;
183     if ($ordbystr)
184         $val = strnatcmp($a[$ordby], $b[$ordby]);
185     else
186         $val = ($a[$ordby] == $b[$ordby]) ? 0 : (($a[$ordby] < $b[$ordby]) ? -1: 1);
187     if (isset($_GET['dir']) && $_GET['dir'])
188         $val = -1*$val;
189     return $val;
190 }
191
192 // Global info array
193 $info = eaccelerator_info();
194
195 ?>
196 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
197 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
198 <head>
199     <title>eAccelerator control panel</title>
200     <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
201     <meta http-equiv="Content-Style-Type" content="text/css" />
202     <meta http-equiv="Content-Language" content="en" />
203
204     <style type="text/css" media="all">
205         body {background-color: #ffffff; color: #000000;margin: 0px;}
206         body, td {font-family: Tahoma, sans-serif;font-size: 12pt;}
207
208         a:link {color: #ff0000; text-decoration: none;}
209         a:visited {color: #ff0000; text-decoration: none;}
210         a:active {color: #aa0000; text-decoration: none;}
211         a:hover {color: #aa0000; text-decoration: none;}
212        
213         .head1 {background-color: #A9CFDD; width: 100%; font-size: 32px; color: #ffffff;padding-top: 20px;font-family: Tahoma, sans-serif;}
214         .head1_item {padding-left: 15px;}
215         .head2 {background-color: #62ADC2; width: 100%; font-size: 18px; color: #ffffff;text-align: right; font-family: Tahoma, sans-serif;border-top: #ffffff 2px solid;}
216         .head2 a:link {color: #ffffff;}
217         .head2 a:visited {color: #ffffff;}
218         .head2 a:active {color: #ffffff;}
219         .head2 a:hover {color: #000000;}
220
221         .menuitem {padding-left: 15px;padding-right: 15px;}
222         .menuitem_sel {padding-left: 15px;padding-right: 15px;background-color: #ffffff; color: #000000;}
223         .menuitem_hov {padding-left: 15px;padding-right: 15px;cursor:pointer;color: #000000;}
224         .mnbody {padding:15px; padding-top: 30px; margin-right: auto; margin-left: auto; text-align: center;bottom: 60px;}
225
226         .mnbody table {border-collapse: collapse; margin-right: auto; margin-left: auto;}
227        
228         td {padding: 3px 10px 3px 10px; border: #ffffff 2px solid;vertical-align:top}
229         .el {text-align: left;background-color: #e1eff8;}
230         .er {text-align: right;background-color: #e1eff8;}
231         .ec {text-align: center;background-color: #e1eff8;}
232
233         .fl {text-align: left;background-color: #efefef;}
234         .fr {text-align: right;background-color: #efefef;}
235
236         .h {text-align: center; font-weight: bold;}
237         .h a:link {color: #000000;}
238         .h a:visited {color: #000000;}
239         .h a:active {color: #ababab;}
240         .h a:hover {color: #ababab;}
241
242         .hgraph {width:100%;}
243         .hgraph td {border: 0px;padding: 0px;}
244         .hgraph_pri {background-color: #62ADC2;}
245         .hgraph_sec {}
246        
247        
248         .footer {width: 100%;text-align: center;font-size: 9pt;color: #ababab;}
249         .footer a:link {color: #ababab;}
250         .footer a:visited {color: #ababab;}
251         .footer a:active {color: #000000;}
252         .footer a:hover {color: #000000;}
253        
254         small {font-size: 10pt;}
255         .s {color: #676767;}
256
257     </style>
258    
259     <script type="text/javascript">
260       function menusel(i) {
261         if (i.className == "menuitem_hov") i.className = "menuitem";
262         else if (i.className == "menuitem") i.className = "menuitem_hov";
263       }
264       function gosec(i) {
265         document.location = "<?php echo $_SERVER['PHP_SELF']?>?sec="+i;
266       }
267     </script>
268    
269 </head>
270
271 <body>
272 <div class="head1"><span class="head1_item">eAccelerator control panel</span></div>
273 <div class="head2">
274 <?php
275 /*
276     Check if eA was compiled with WITH_EACCELERATOR_CONTENT_CACHING) || WITH_EACCELERATOR_SESSIONS || WITH_EACCELERATOR_SHM
277     if yes, show 'User Cache' tab, else dont
278 */
279 if (function_exists(eaccelerator_list_keys)) {
280     $items = array(0 => 'Status', 1 => 'Script Cache', 2 => 'User Cache');
281 } else {
282     $items = array(0 => 'Status', 1 => 'Script Cache');
283 }
284
285 foreach ($items as $i => $item) {
286     echo '<span class="menuitem'.(($sec == $i)?'_sel':'').'" onmouseover="menusel(this)" onmouseout="menusel(this)" onclick="gosec('.$i.')">'.(($sec != $i)?'<a href="'.$_SERVER['PHP_SELF'].'?sec='.$i.'">'.$item.'</a>':$item).'</span>';
287
288 ?>
289 </div>
290 <div class="mnbody">
291 <?php
292 switch ($sec) {
293     default:
294     case 0:
295         /******************************     STATUS / CONTROL     ******************************/
296
297         if (isset($_POST['cachingoff'])) eaccelerator_caching(false);
298         if (isset($_POST['cachingon'])) eaccelerator_caching(true);
299
300         if (isset($_POST['optoff']) && function_exists('eaccelerator_optimizer')) eaccelerator_optimizer(false);
301         if (isset($_POST['opton']) && function_exists('eaccelerator_optimizer')) eaccelerator_optimizer(true);
302
303         if (isset($_POST['clear'])) eaccelerator_clear();
304         if (isset($_POST['clean'])) eaccelerator_clean();
305         if (isset($_POST['purge'])) eaccelerator_purge();
306
307         $info = eaccelerator_info();
308
309 ?>
310 <table>
311 <tr><td>
312
313 <form action="<?php echo $_SERVER['PHP_SELF']?>?sec=0" method="post">
314 <table>
315 <tr>
316     <td class="h" colspan="2">Usage statistics</td>
317 </tr>
318 <tr>
319     <td class="er">Caching enabled</td>
320     <td class="fl"><?php echo $info['cache'] ? '<span style="color:green"><b>yes</b></span>&nbsp;&nbsp;&nbsp;<input type="submit" name="cachingoff" value=" Disable "/>':'<span style="color:red"><b>no</b></span>&nbsp;&nbsp;&nbsp;<input type="submit" name="cachingon" value=" Enable "/>' ?></td>
321 </tr>
322 <tr>
323     <td class="er">Optimizer enabled</td>
324     <td class="fl"><?php echo $info['optimizer'] ? '<span style="color:green"><b>yes</b></span>&nbsp;&nbsp;&nbsp;<input type="submit" name="optoff" value=" Disable "/>':'<span style="color:red"><b>no</b></span>&nbsp;&nbsp;&nbsp;<input type="submit" name="opton" value=" Enable "/>' ?></td>
325 </tr>
326 <tr>
327     <td class="er">Total memory</td>
328     <td class="fl"><?php echo format_size($info['memorySize']); ?></td>
329 </tr>
330 <tr>
331     <td class="er">Memory in use</td>
332     <td class="fl"><?php echo format_size($info['memoryAllocated']).' ('.number_format(100 * $info['memoryAllocated'] / max(1, $info['memorySize']), 0).'%)';?></td>
333 </tr>
334 <tr>
335     <td class="er" colspan="2"><?php echo space_graph($info['memoryAllocated'], $info['memorySize']);?></td>
336 </tr>
337 <tr>
338     <td class="er">Free memory</td>
339     <td class="fl"><?php echo format_size($info['memoryAvailable'])?></td>
340 </tr>
341 <tr>
342     <td class="er">Cached scripts</td>
343     <td class="fl"><?php echo number_format($info['cachedScripts']); ?></td>
344 </tr>
345 <tr>
346     <td class="er">Removed scripts</td>
347     <td class="fl"><?php echo number_format($info['removedScripts']); ?></td>
348 </tr>
349 <tr>
350     <td class="er">Cached keys</td>
351     <td class="fl"><?php echo number_format($info['cachedKeys']); ?></td>
352 </tr>
353 </table>
354 </form>
355
356 </td><td>
357
358 <table>
359 <tr>
360     <td class="h" colspan="2">Build information</td>
361 </tr>
362 <tr>
363     <td class="er">eAccelerator version</td>
364     <td class="fl"><?php echo $info['version']; ?></td>
365 </tr>
366 <tr>
367     <td class="er">Shared memory type</td>
368     <td class="fl"><?php echo $info['shm_type']; ?></td>
369 </tr>
370 <tr>
371     <td class="er">Semaphore type</td>
372     <td class="fl"><?php echo $info['sem_type']; ?></td>
373 </tr>
374 </table>
375
376 </td></tr>
377 </table>
378
379 <br/><br/>
380
381 <form action="<?php echo $_SERVER['PHP_SELF']?>?sec=0" method="post">
382 <table>
383 <tr>
384     <td class="h" colspan="2">Maintenance</td>
385 </tr>
386 <tr>
387     <td class="ec"><input type="submit" name="clear" value=" Clear cache "/></td>
388     <td class="fl">Removed all scripts and data from shared memory and / or disk.</td>
389 </tr>
390 <tr>
391     <td class="ec"><input type="submit" name="clean" value=" Delete expired "/></td>
392     <td class="fl">Removed all expired scripts and data from shared memory and / or disk.</td>
393 </tr>
394 <tr>
395     <td class="ec"><input type="submit" name="purge" value=" Purge cache "/></td>
396     <td class="fl">Delete all 'removed' scripts from shared memory.</td>
397 </tr>
398 </table>
399 </form>
400
401 <?php
402         break;
403     case 1:
404         /******************************     SCRIPT CACHE     ******************************/
405     
406         $scripts = eaccelerator_cached_scripts();
407         $removed = eaccelerator_removed_scripts();
408     
409         // combine arrays
410         function removedmod ($val) {
411             $val['removed'] = true;
412             return $val;
413         }
414         $scripts = array_merge($scripts, array_map('removedmod', $removed));
415     
416         // search
417         function scriptsearch ($val) {
418             $str = isset($_GET['str']) ? $_GET['str'] : '';
419             return preg_match('/'.preg_quote($str, '/').'/i', $val['file']);
420         }
421         $scripts = array_filter($scripts, 'scriptsearch');
422     
423         // sort
424         $ordby = isset($_GET['ordby']) ? intval($_GET['ordby']) : 0;
425         switch ($ordby) {
426             default:
427             case 0: $ordby = 'file'; $ordbystr = true; break;
428             case 1: $ordby = 'mtime'; $ordbystr = false; break;
429             case 2: $ordby = 'size'; $ordbystr = false; break;
430             case 3: $ordby = 'reloads'; $ordbystr = false; break;
431             case 4: $ordby = 'hits'; $ordbystr = false; break;
432         }
433         usort($scripts, 'arrsort');
434  
435         // slice
436         $numtot = count($scripts);
437
438         $pg = (isset($_GET['pg']) ? (int)$_GET['pg'] : 0); // zero-starting
439         $pgs = ceil($numtot/$npp);
440
441         if ($pg + 1 > $pgs)
442             $pg = $pgs-1;
443         if ($pg < 0)
444             $pg = 0;
445
446         $scripts = array_slice($scripts, $pg*$npp, $npp);
447         $numres = count($scripts);
448 ?>
449 <table class="center">
450 <tr>
451     <td class="h" colspan="2">Search</td>
452 </tr>
453 <tr>
454     <form action="<?php echo $_SERVER['PHP_SELF']?>" method="get"><input type="hidden" name="sec" value="1"/>
455     <td class="el">Match filename:</td>
456     <td class="fl"><input type="text" name="str" size="40" value="<?php echo isset($_GET['str']) ? $_GET['str'] : '' ?>"/>&nbsp;<input type="submit" value=" Find "/></td>
457     </form>
458 </tr>
459 </table>
460
461 <br/><br/>
462
463 <?php
464         if (count($scripts) == 0)
465             echo '<div class="center"><i>No scripts found</i></div>';
466         else {
467 ?>
468 <table class="center">
469 <tr>
470     <td colspan="1" style="text-align: left">Showing <?php echo $pg*$npp+1?> &ndash; <?php echo $pg*$npp+min($npp, $numres)?> of <?php echo $numtot?></td>
471     <td colspan="4" style="text-align: right;"><small><?php echo pageselstr($pg, $pgs)?></small></td>
472 </tr>
473 <tr>
474     <td class="h"><?php echo colheadstr('File', 0)?></td>
475     <td class="h"><?php echo colheadstr('Last Modified', 1)?></td>
476     <td class="h"><?php echo colheadstr('Size', 2)?></td>
477     <td class="h"><?php echo colheadstr('Reloads', 3)?></td>
478     <td class="h"><?php echo colheadstr('Hits', 4)?></td>
479 </tr>
480 <?php
481             $disassembler = function_exists('eaccelerator_dasm_file');
482             for ($i = 0; $i < $numres; $i++) {
483                 $removed = (isset($scripts[$i]['removed']) && $scripts[$i]['removed']);
484                 if ($disassembler && !$removed) {
485                     $file_col = sprintf('<a href="dasm.php?file=%s">%s</a>', $scripts[$i]['file'], $scripts[$i]['file']);
486                 } elseif ($removed) {
487                     $file_col = sprintf('<span class="s">%s</span>', $scripts[$i]['file']);   
488                 } else {
489                     $file_col = $scripts[$i]['file'];
490                 }
491 ?>
492 <tr>
493     <td class="el"><small><?php echo $file_col ?></small></td>
494     <td class="fl"><small><?php echo date('Y-m-d H:i:s', $scripts[$i]['mtime'])?></small></td>
495     <td class="fr"><small><?php echo format_size($scripts[$i]['size'])?></small></td>
496     <td class="fr"><small><?php echo $scripts[$i]['reloads']?> (<?php echo $scripts[$i]['usecount']?>)</small></td>
497     <td class="fr"><small><?php echo number_format($scripts[$i]['hits'])?></small></td>
498 </tr>
499 <?php
500       }
501 ?>
502 <tr>
503     <td colspan="1" style="text-align: left">&nbsp;</td>
504     <td colspan="4" style="text-align: right;"><small><?php echo pageselstr($pg, ceil($numtot/$npp))?></small></td>
505 </tr>
506 </table>
507 <?php
508             }
509             break;
510         case 2:
511         /******************************     USER CACHE     ******************************/
512