source: trunk/zpush/z-push-top.php @ 7589

Revision 7589, 28.9 KB checked in by douglas, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

  • Property svn:executable set to *
Line 
1#!/usr/bin/php
2<?php
3/***********************************************
4* File      :   z-push-top.php
5* Project   :   Z-Push
6* Descr     :   Shows realtime information about
7*               connected devices and active
8*               connections in a top-style format.
9*
10* Created   :   07.09.2011
11*
12* Copyright 2007 - 2012 Zarafa Deutschland GmbH
13*
14* This program is free software: you can redistribute it and/or modify
15* it under the terms of the GNU Affero General Public License, version 3,
16* as published by the Free Software Foundation with the following additional
17* term according to sec. 7:
18*
19* According to sec. 7 of the GNU Affero General Public License, version 3,
20* the terms of the AGPL are supplemented with the following terms:
21*
22* "Zarafa" is a registered trademark of Zarafa B.V.
23* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
24* The licensing of the Program under the AGPL does not imply a trademark license.
25* Therefore any rights, title and interest in our trademarks remain entirely with us.
26*
27* However, if you propagate an unmodified version of the Program you are
28* allowed to use the term "Z-Push" to indicate that you distribute the Program.
29* Furthermore you may use our trademarks where it is necessary to indicate
30* the intended purpose of a product or service provided you use it in accordance
31* with honest practices in industrial or commercial matters.
32* If you want to propagate modified versions of the Program under the name "Z-Push",
33* you may only do so if you have a written permission by Zarafa Deutschland GmbH
34* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU Affero General Public License for more details.
40*
41* You should have received a copy of the GNU Affero General Public License
42* along with this program.  If not, see <http://www.gnu.org/licenses/>.
43*
44* Consult LICENSE file for details
45************************************************/
46
47include('lib/exceptions/exceptions.php');
48include('lib/core/zpushdefs.php');
49include('lib/core/zpush.php');
50include('lib/core/zlog.php');
51include('lib/core/interprocessdata.php');
52include('lib/core/topcollector.php');
53include('lib/utils/utils.php');
54include('lib/request/request.php');
55include('lib/request/requestprocessor.php');
56include('config.php');
57include('version.php');
58
59/************************************************
60 * MAIN
61 */
62    declare(ticks = 1);
63    define('BASE_PATH_CLI',  dirname(__FILE__) ."/");
64
65    try {
66        ZPush::CheckConfig();
67        if (!function_exists("pcntl_signal"))
68            throw new FatalException("Function pcntl_signal() is not available. Please install package 'php5-pcntl' (or similar) on your system.");
69
70        $zpt = new ZPushTop();
71
72        // check if help was requested from CLI
73        if (in_array('-h', $argv) || in_array('--help', $argv)) {
74            echo $zpt->UsageInstructions();
75            exit(1);
76        }
77
78        if ($zpt->IsAvailable()) {
79            pcntl_signal(SIGINT, array($zpt, "SignalHandler"));
80            $zpt->run();
81            $zpt->scrClear();
82            system("stty sane");
83        }
84        else
85            echo "Z-Push shared memory interprocess communication is not available.\n";
86    }
87    catch (ZPushException $zpe) {
88        die(get_class($zpe) . ": ". $zpe->getMessage() . "\n");
89    }
90
91    echo "terminated\n";
92
93
94/************************************************
95 * Z-Push-Top
96 */
97class ZPushTop {
98    // show options
99    const SHOW_DEFAULT = 0;
100    const SHOW_ACTIVE_ONLY = 1;
101    const SHOW_UNKNOWN_ONLY = 2;
102    const SHOW_TERM_DEFAULT_TIME = 5; // 5 secs
103
104    private $topCollector;
105    private $starttime;
106    private $action;
107    private $filter;
108    private $status;
109    private $statusexpire;
110    private $wide;
111    private $wasEnabled;
112    private $terminate;
113    private $scrSize;
114    private $pingInterval;
115    private $showPush;
116    private $showTermSec;
117
118    private $linesActive = array();
119    private $linesOpen = array();
120    private $linesUnknown = array();
121    private $linesTerm = array();
122    private $pushConn = 0;
123    private $activeConn = array();
124    private $activeHosts = array();
125    private $activeUsers = array();
126    private $activeDevices = array();
127
128    /**
129     * Constructor
130     *
131     * @access public
132     */
133    public function ZPushTop() {
134        $this->starttime = time();
135        $this->currenttime = time();
136        $this->action = "";
137        $this->filter = false;
138        $this->status = false;
139        $this->statusexpire = 0;
140        $this->helpexpire = 0;
141        $this->doingTail = false;
142        $this->wide = false;
143        $this->terminate = false;
144        $this->showPush = true;
145        $this->showOption = self::SHOW_DEFAULT;
146        $this->showTermSec = self::SHOW_TERM_DEFAULT_TIME;
147        $this->scrSize = array('width' => 80, 'height' => 24);
148        $this->pingInterval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 12;
149
150        // get a TopCollector
151        $this->topCollector = new TopCollector();
152    }
153
154    /**
155     * Requests data from the running Z-Push processes
156     *
157     * @access private
158     * @return
159     */
160    private function initialize() {
161        // request feedback from active processes
162        $this->wasEnabled = $this->topCollector->CollectData();
163
164        // remove obsolete data
165        $this->topCollector->ClearLatest(true);
166
167        // start with default colours
168        $this->scrDefaultColors();
169    }
170
171    /**
172     * Main loop of Z-Push-top
173     * Runs until termination is requested
174     *
175     * @access public
176     * @return
177     */
178    public function run() {
179        $this->initialize();
180
181        do {
182            $this->currenttime = time();
183
184            // see if shared memory is active
185            if (!$this->IsAvailable())
186                $this->terminate = true;
187
188            // active processes should continue sending data
189            $this->topCollector->CollectData();
190
191            // get and process data from processes
192            $this->topCollector->ClearLatest();
193            $topdata = $this->topCollector->ReadLatest();
194            $this->processData($topdata);
195
196            // clear screen
197            $this->scrClear();
198
199            // check if screen size changed
200            $s = $this->scrGetSize();
201            if ($this->scrSize['width'] != $s['width']) {
202                if ($s['width'] > 180)
203                    $this->wide = true;
204                else
205                    $this->wide = false;
206            }
207            $this->scrSize = $s;
208
209            // print overview
210            $this->scrOverview();
211
212            // wait for user input
213            $this->readLineProcess();
214        }
215        while($this->terminate != true);
216    }
217
218    /**
219     * Indicates if TopCollector is available collecting data
220     *
221     * @access public
222     * @return boolean
223     */
224    public function IsAvailable() {
225        return $this->topCollector->IsActive();
226    }
227
228    /**
229     * Processes data written by the running processes
230     *
231     * @param array $data
232     *
233     * @access private
234     * @return
235     */
236    private function processData($data) {
237        $this->linesActive = array();
238        $this->linesOpen = array();
239        $this->linesUnknown = array();
240        $this->linesTerm = array();
241        $this->pushConn = 0;
242        $this->activeConn = array();
243        $this->activeHosts = array();
244        $this->activeUsers = array();
245        $this->activeDevices = array();
246
247        if (!is_array($data))
248            return;
249
250        foreach ($data as $devid=>$users) {
251            foreach ($users as $user=>$pids) {
252                foreach ($pids as $pid=>$line) {
253                    if (!is_array($line))
254                        continue;
255
256                    $line['command'] = Utils::GetCommandFromCode($line['command']);
257
258                    if ($line["ended"] == 0) {
259                        $this->activeDevices[$devid] = 1;
260                        $this->activeUsers[$user] = 1;
261                        $this->activeConn[$pid] = 1;
262                        $this->activeHosts[$line['ip']] = 1;
263
264                        $line["time"] = $this->currenttime - $line['start'];
265                        if ($line['push'] === true) $this->pushConn += 1;
266
267                        // ignore push connections
268                        if ($line['push'] === true && ! $this->showPush)
269                            continue;
270
271                        if ($this->filter !== false) {
272                            $f = $this->filter;
273                            if (!($line["pid"] == $f || $line["ip"] == $f || strtolower($line['command']) == strtolower($f) || preg_match("/.*?$f.*?/i", $line['user']) ||
274                                preg_match("/.*?$f.*?/i", $line['devagent']) || preg_match("/.*?$f.*?/i", $line['devid']) || preg_match("/.*?$f.*?/i", $line['addinfo']) ))
275                                continue;
276                        }
277
278                        $lastUpdate = $this->currenttime - $line["update"];
279                        if ($this->currenttime - $line["update"] < 2)
280                            $this->linesActive[$line["update"].$line["pid"]] = $line;
281                        else if (($line['push'] === true  && $lastUpdate > ($this->pingInterval+2)) || ($line['push'] !== true  && $lastUpdate > 4))
282                            $this->linesUnknown[$line["update"].$line["pid"]] = $line;
283                        else
284                            $this->linesOpen[$line["update"].$line["pid"]] = $line;
285                    }
286                    else {
287                        // do not show terminated + expired connections
288                        if ($line['ended'] + $this->showTermSec < $this->currenttime)
289                            continue;
290
291                        if ($this->filter !== false) {
292                            $f = $this->filter;
293                            if (!($line['pid'] == $f || $line['ip'] == $f || strtolower($line['command']) == strtolower($f) || preg_match("/.*?$f.*?/i", $line['user']) ||
294                                preg_match("/.*?$f.*?/i", $line['devagent']) || preg_match("/.*?$f.*?/i", $line['devid']) || preg_match("/.*?$f.*?/i", $line['addinfo']) ))
295                                continue;
296                        }
297
298                        $line['time'] = $line['ended'] - $line['start'];
299                        $this->linesTerm[$line['update'].$line['pid']] = $line;
300                    }
301                }
302            }
303        }
304
305        // sort by execution time
306        krsort($this->linesActive);
307        krsort($this->linesOpen);
308        krsort($this->linesUnknown);
309        krsort($this->linesTerm);
310    }
311
312    /**
313     * Prints data to the terminal
314     *
315     * @access private
316     * @return
317     */
318    private function scrOverview() {
319        $linesAvail = $this->scrSize['height'] - 8;
320        $lc = 1;
321        $this->scrPrintAt($lc,0, "\033[1mZ-Push top live statistics\033[0m\t\t\t\t\t". @strftime("%d/%m/%Y %T")."\n"); $lc++;
322
323        $this->scrPrintAt($lc,0, sprintf("Open connections: %d\t\t\t\tUsers:\t %d\tZ-Push:   %s ",count($this->activeConn),count($this->activeUsers), $this->getVersion())); $lc++;
324        $this->scrPrintAt($lc,0, sprintf("Push connections: %d\t\t\t\tDevices: %d\tPHP-MAPI: %s", $this->pushConn, count($this->activeDevices),phpversion("mapi"))); $lc++;
325        $this->scrPrintAt($lc,0, sprintf("                                                Hosts:\t %d", $this->pushConn, count($this->activeHosts))); $lc++;
326        $lc++;
327
328        $this->scrPrintAt($lc,0, "\033[4m". $this->getLine(array('pid'=>'PID', 'ip'=>'IP', 'user'=>'USER', 'command'=>'COMMAND', 'time'=>'TIME', 'devagent'=>'AGENT', 'devid'=>'DEVID', 'addinfo'=>'Additional Information')). str_repeat(" ",20)."\033[0m"); $lc++;
329
330        // print help text if requested
331        $hl = 0;
332        if ($this->helpexpire > $this->currenttime) {
333            $help = $this->scrHelp();
334            $linesAvail -= count($help);
335            $hl = $this->scrSize['height'] - count($help) -1;
336            foreach ($help as $h) {
337                $this->scrPrintAt($hl,0, $h);
338                $hl++;
339            }
340        }
341
342        $toPrintActive = $linesAvail;
343        $toPrintOpen = $linesAvail;
344        $toPrintUnknown = $linesAvail;
345        $toPrintTerm = $linesAvail;
346
347        // default view: show all unknown, no terminated and half active+open
348        if (count($this->linesActive) + count($this->linesOpen) + count($this->linesUnknown) > $linesAvail) {
349            $toPrintUnknown = count($this->linesUnknown);
350            $toPrintActive = count($this->linesActive);
351            $toPrintOpen = $linesAvail-$toPrintUnknown-$toPrintActive;
352            $toPrintTerm = 0;
353        }
354
355        if ($this->showOption == self::SHOW_ACTIVE_ONLY) {
356            $toPrintActive = $linesAvail;
357            $toPrintOpen = 0;
358            $toPrintUnknown = 0;
359            $toPrintTerm = 0;
360        }
361
362        if ($this->showOption == self::SHOW_UNKNOWN_ONLY) {
363            $toPrintActive = 0;
364            $toPrintOpen = 0;
365            $toPrintUnknown = $linesAvail;
366            $toPrintTerm = 0;
367        }
368
369        $linesprinted = 0;
370        foreach ($this->linesActive as $time=>$l) {
371            if ($linesprinted >= $toPrintActive)
372                break;
373
374            $this->scrPrintAt($lc,0, "\033[01m" . $this->getLine($l)  ."\033[0m");
375            $lc++;
376            $linesprinted++;
377        }
378
379        $linesprinted = 0;
380        foreach ($this->linesOpen as $time=>$l) {
381            if ($linesprinted >= $toPrintOpen)
382                break;
383
384            $this->scrPrintAt($lc,0, $this->getLine($l));
385            $lc++;
386            $linesprinted++;
387        }
388
389        $linesprinted = 0;
390        foreach ($this->linesUnknown as $time=>$l) {
391            if ($linesprinted >= $toPrintUnknown)
392                break;
393
394            $color = "0;31m";
395            if ($l['push'] == false && $time - $l["start"] > 30)
396                $color = "1;31m";
397            $this->scrPrintAt($lc,0, "\033[0". $color . $this->getLine($l)  ."\033[0m");
398            $lc++;
399            $linesprinted++;
400        }
401
402        if ($toPrintTerm > 0)
403            $toPrintTerm = $linesAvail - $lc +6;
404
405        $linesprinted = 0;
406        foreach ($this->linesTerm as $time=>$l){
407            if ($linesprinted >= $toPrintTerm)
408                break;
409
410            $this->scrPrintAt($lc,0, "\033[01;30m" . $this->getLine($l)  ."\033[0m");
411            $lc++;
412            $linesprinted++;
413        }
414
415        // add the lines used when displaying the help text
416        $lc += $hl;
417        $this->scrPrintAt($lc,0, "\033[K"); $lc++;
418        $this->scrPrintAt($lc,0, "Colorscheme: \033[01mActive  \033[0mOpen  \033[01;31mUnknown  \033[01;30mTerminated\033[0m");
419
420        // remove old status
421        if ($this->statusexpire < $this->currenttime)
422            $this->status = false;
423
424        // show request information and help command
425        if ($this->starttime + 6 > $this->currenttime) {
426            $this->status = sprintf("Requesting information (takes up to %dsecs)", $this->pingInterval). str_repeat(".", ($this->currenttime-$this->starttime)) . "  type \033[01;31mh\033[00;31m or \033[01;31mhelp\033[00;31m for usage instructions";
427            $this->statusexpire = $this->currenttime+1;
428        }
429
430
431        $str = "";
432        if (! $this->showPush)
433            $str .= "\033[00;32mPush: \033[01;32mNo\033[0m   ";
434
435        if ($this->showOption == self::SHOW_ACTIVE_ONLY)
436            $str .= "\033[01;32mActive only\033[0m   ";
437
438        if ($this->showOption == self::SHOW_UNKNOWN_ONLY)
439            $str .= "\033[01;32mUnknown only\033[0m   ";
440
441        if ($this->showTermSec != self::SHOW_TERM_DEFAULT_TIME)
442            $str .= "\033[01;32mTerminated: ". $this->showTermSec. "s\033[0m   ";
443
444        if ($this->filter !== false || ($this->status !== false && $this->statusexpire > $this->currenttime)) {
445            // print filter in green
446            if ($this->filter !== false)
447                $str .= "\033[00;32mFilter: \033[01;32m$this->filter\033[0m   ";
448            // print status in red
449            if ($this->status !== false)
450                $str .= "\033[00;31m$this->status\033[0m";
451        }
452        $this->scrPrintAt(5,0, $str);
453
454        $this->scrPrintAt(4,0,"Action: \033[01m".$this->action . "\033[0m");
455    }
456
457    /**
458     * Waits for a keystroke and processes the requested command
459     *
460     * @access private
461     * @return
462     */
463    private function readLineProcess() {
464        $ans = explode("^^", `bash -c "read -n 1 -t 1 ANS ; echo \\\$?^^\\\$ANS;"`);
465
466        if ($ans[0] < 128) {
467            if (isset($ans[1]) && bin2hex(trim($ans[1])) == "7f") {
468                $this->action = substr($this->action,0,-1);
469            }
470
471            if (isset($ans[1]) && $ans[1] != "" ){
472                $this->action .= trim(preg_replace("/[^A-Za-z0-9:]/","",$ans[1]));
473            }
474
475            if (bin2hex($ans[0]) == "30" && bin2hex($ans[1]) == "0a")  {
476                $cmds = explode(':', $this->action);
477                if ($cmds[0] == "quit" || $cmds[0] == "q" || (isset($cmds[1]) && $cmds[0] == "" && $cmds[1] == "q")) {
478                    $this->topCollector->CollectData(true);
479                    $this->topCollector->ClearLatest(true);
480
481                    $this->terminate = true;
482                }
483                else if ($cmds[0] == "clear" ) {
484                    $this->topCollector->ClearLatest(true);
485                    $this->topCollector->CollectData(true);
486                    $this->topCollector->ReInitSharedMem();
487                }
488                else if ($cmds[0] == "filter" || $cmds[0] == "f") {
489                    if (!isset($cmds[1]) || $cmds[1] == "") {
490                        $this->filter = false;
491                        $this->status = "No filter";
492                        $this->statusexpire = $this->currenttime+5;
493                    }
494                    else {
495                        $this->filter = $cmds[1];
496                        $this->status = false;
497                    }
498                }
499                else if ($cmds[0] == "option" || $cmds[0] == "o") {
500                    if (!isset($cmds[1]) || $cmds[1] == "") {
501                        $this->status = sprintf("Option value needs to be specified. See 'help' or 'h' for instructions", $cmds[1]);
502                        $this->statusexpire = $this->currenttime+5;
503                    }
504                    else if ($cmds[1] == "p" || $cmds[1] == "push" || $cmds[1] == "ping")
505                        $this->showPush = !$this->showPush;
506                    else if ($cmds[1] == "a" || $cmds[1] == "active")
507                        $this->showOption = self::SHOW_ACTIVE_ONLY;
508                    else if ($cmds[1] == "u" || $cmds[1] == "unknown")
509                        $this->showOption = self::SHOW_UNKNOWN_ONLY;
510                    else if ($cmds[1] == "d" || $cmds[1] == "default") {
511                        $this->showOption = self::SHOW_DEFAULT;
512                        $this->showTermSec = self::SHOW_TERM_DEFAULT_TIME;
513                        $this->showPush = true;
514                    }
515                    else if (is_numeric($cmds[1]))
516                        $this->showTermSec = $cmds[1];
517                    else {
518                        $this->status = sprintf("Option '%s' unknown", $cmds[1]);
519                        $this->statusexpire = $this->currenttime+5;
520                    }
521                }
522                else if ($cmds[0] == "reset" || $cmds[0] == "r") {
523                    $this->filter = false;
524                    $this->wide = false;
525                    $this->helpexpire = 0;
526                    $this->status = "resetted";
527                    $this->statusexpire = $this->currenttime+2;
528                }
529                else if ($cmds[0] == "wide" || $cmds[0] == "w") {
530                    $this->wide = true;
531                    $this->status = "w i d e  view";
532                    $this->statusexpire = $this->currenttime+2;
533                }
534                else if ($cmds[0] == "help" || $cmds[0] == "h") {
535                    $this->helpexpire = $this->currenttime+20;
536                }
537                else if (($cmds[0] == "log" || $cmds[0] == "l") && isset($cmds[1]) ) {
538                    if (!file_exists(LOGFILE)) {
539                        $this->status = "Logfile can not be found: ". LOGFILE;
540                    }
541                    else {
542                        system('bash -c "fgrep -a '.escapeshellarg($cmds[1]).' '. LOGFILE .' | less +G" > `tty`');
543                        $this->status = "Returning from log, updating data";
544                    }
545                    $this->statusexpire = time()+5; // it might be much "later" now
546                }
547                else if (($cmds[0] == "tail" || $cmds[0] == "t")) {
548                    if (!file_exists(LOGFILE)) {
549                        $this->status = "Logfile can not be found: ". LOGFILE;
550                    }
551                    else {
552                        $this->doingTail = true;
553                        $this->scrClear();
554                        $this->scrPrintAt(1,0,$this->scrAsBold("Press CTRL+C to return to Z-Push-Top\n\n"));
555                        $secondary = "";
556                        if (isset($cmds[1])) $secondary =  " -n 200 | grep ".escapeshellarg($cmds[1]);
557                        system('bash -c "tail -f '. LOGFILE . $secondary . '" > `tty`');
558                        $this->doingTail = false;
559                        $this->status = "Returning from tail, updating data";
560                    }
561                    $this->statusexpire = time()+5; // it might be much "later" now
562                }
563
564                else if ($cmds[0] != "") {
565                    $this->status = sprintf("Command '%s' unknown", $cmds[0]);
566                    $this->statusexpire = $this->currenttime+8;
567                }
568                $this->action = "";
569            }
570        }
571    }
572
573    /**
574     * Signal handler function
575     *
576     * @param int   $signo      signal number
577     *
578     * @access public
579     * @return
580     */
581    public function SignalHandler($signo) {
582        // don't terminate if the signal was sent by terminating tail
583        if (!$this->doingTail) {
584            $this->topCollector->CollectData(true);
585            $this->topCollector->ClearLatest(true);
586            $this->terminate = true;
587        }
588    }
589
590    /**
591     * Returns usage instructions
592     *
593     * @return string
594     * @access public
595     */
596    public function UsageInstructions() {
597        $help = "Usage:\n\tz-push-top.php\n\n" .
598                "  Z-Push-Top is a live top-like overview of what Z-Push is doing. It does not have specific command line options.\n\n".
599                "  When Z-Push-Top is running you can specify certain actions and options which can be executed (listed below).\n".
600                "  This help information can also be shown inside Z-Push-Top by hitting 'help' or 'h'.\n\n";
601        $scrhelp = $this->scrHelp();
602        unset($scrhelp[0]);
603
604        $help .= implode("\n", $scrhelp);
605        $help .= "\n\n";
606        return $help;
607    }
608
609
610    /**
611     * Prints a 'help' text at the end of the page
612     *
613     * @access private
614     * @return array        with help lines
615     */
616    private function scrHelp() {
617        $h = array();
618        $secs = $this->helpexpire - $this->currenttime;
619        $h[] = "Actions supported by Z-Push-Top (help page still displayed for ".$secs."secs)";
620        $h[] = "  ".$this->scrAsBold("Action")."\t\t".$this->scrAsBold("Comment");
621        $h[] = "  ".$this->scrAsBold("h")." or ".$this->scrAsBold("help")."\t\tDisplays this information.";
622        $h[] = "  ".$this->scrAsBold("q").", ".$this->scrAsBold("quit")." or ".$this->scrAsBold(":q")."\t\tExits Z-Push-Top.";
623        $h[] = "  ".$this->scrAsBold("w")." or ".$this->scrAsBold("wide")."\t\tTries not to truncate data. Automatically done if more than 180 columns available.";
624        $h[] = "  ".$this->scrAsBold("f:VAL")." or ".$this->scrAsBold("filter:VAL")."\tOnly display connections which contain VAL. This value is case-insensitive.";
625        $h[] = "  ".$this->scrAsBold("f:")." or ".$this->scrAsBold("filter:")."\t\tWithout a search word: resets the filter.";
626        $h[] = "  ".$this->scrAsBold("l:STR")." or ".$this->scrAsBold("log:STR")."\tIssues 'less +G' on the logfile, after grepping on the optional STR.";
627        $h[] = "  ".$this->scrAsBold("t:STR")." or ".$this->scrAsBold("tail:STR")."\tIssues 'tail -f' on the logfile, grepping for optional STR.";
628        $h[] = "  ".$this->scrAsBold("r")." or ".$this->scrAsBold("reset")."\t\tResets 'wide' or 'filter'.";
629        $h[] = "  ".$this->scrAsBold("o:")." or ".$this->scrAsBold("option:")."\t\tSets display options. Valid options specified below";
630        $h[] = "  ".$this->scrAsBold("  p")." or ".$this->scrAsBold("push")."\t\tLists/not lists active and open push connections.";
631        $h[] = "  ".$this->scrAsBold("  a")." or ".$this->scrAsBold("action")."\t\tLists only active connections.";
632        $h[] = "  ".$this->scrAsBold("  u")." or ".$this->scrAsBold("unknown")."\tLists only unknown connections.";
633        $h[] = "  ".$this->scrAsBold("  10")." or ".$this->scrAsBold("20")."\t\tLists terminated connections for 10 or 20 seconds. Any other number can be used.";
634        $h[] = "  ".$this->scrAsBold("  d")." or ".$this->scrAsBold("default")."\tUses default options";
635
636        return $h;
637    }
638
639    /**
640     * Encapsulates string with different color escape characters
641     *
642     * @param string        $text
643     *
644     * @access private
645     * @return string       same text as bold
646     */
647    private function scrAsBold($text) {
648        return "\033[01m" . $text  ."\033[0m";
649    }
650
651    /**
652     * Prints one line of precessed data
653     *
654     * @param array     $l      line information
655     *
656     * @access private
657     * @return string
658     */
659    private function getLine($l) {
660        if ($this->wide === true)
661            return sprintf("%s%s%s%s%s%s%s%s", $this->ptStr($l['pid'],6), $this->ptStr($l['ip'],16), $this->ptStr($l['user'],24), $this->ptStr($l['command'],16), $this->ptStr($this->sec2min($l['time']),8), $this->ptStr($l['devagent'],28), $this->ptStr($l['devid'],30, true), $l['addinfo']);
662        else
663            return sprintf("%s%s%s%s%s%s%s%s", $this->ptStr($l['pid'],6), $this->ptStr($l['ip'],10), $this->ptStr($l['user'],8), $this->ptStr($l['command'],11), $this->ptStr($this->sec2min($l['time']),6), $this->ptStr($l['devagent'],20), $this->ptStr($l['devid'],12, true), $l['addinfo']);
664    }
665
666    /**
667     * Pads and trims string
668     *
669     * @param string    $string     to be trimmed/padded
670     * @param int       $size       characters to be considered
671     * @param boolean   $cutmiddle  (optional) indicates where to long information should
672     *                              be trimmed of, false means at the end
673     *
674     * @access private
675     * @return string
676     */
677    private function ptStr($str, $size, $cutmiddle = false) {
678        if (strlen($str) < $size)
679            return str_pad($str, $size);
680        else if ($cutmiddle == true) {
681            $cut = ($size-2)/2;
682            return $this->ptStr(substr($str,0,$cut) ."..". substr($str,(-1)*($cut-1)), $size);
683        }
684        else {
685            return substr($str,0,$size-3).".. ";
686        }
687    }
688
689    /**
690     * Tries to discover the size of the current terminal
691     *
692     * @access private
693     * @return array        'width' and 'height' as keys
694     */
695    private function scrGetSize() {
696        preg_match_all("/rows.([0-9]+);.columns.([0-9]+);/", strtolower(exec('stty -a | fgrep columns')), $output);
697        if(sizeof($output) == 3)
698            return array('width' => $output[2][0], 'height' => $output[1][0]);
699
700        return array('width' => 80, 'height' => 24);
701    }
702
703    /**
704     * Returns the version of the current Z-Push installation
705     *
706     * @access private
707     * @return string
708     */
709    private function getVersion() {
710        if (ZPUSH_VERSION == "SVN checkout" && file_exists(REAL_BASE_PATH.".svn/entries")) {
711            $svn = file(REAL_BASE_PATH.".svn/entries");
712            return "SVN " . substr(trim($svn[4]),stripos($svn[4],"z-push")+7) ." r".trim($svn[3]);
713        }
714        return ZPUSH_VERSION;
715    }
716
717    /**
718     * Converts seconds in MM:SS
719     *
720     * @param int   $s      seconds
721     *
722     * @access private
723     * @return string
724     */
725    private function sec2min($s) {
726        if (!is_int($s))
727            return $s;
728        return sprintf("%02.2d:%02.2d", floor($s/60), $s%60);
729    }
730
731    /**
732     * Resets the default colors of the terminal
733     *
734     * @access private
735     * @return
736     */
737    private function scrDefaultColors() {
738        echo "\033[0m";
739    }
740
741    /**
742     * Clears screen of the terminal
743     *
744     * @param array $data
745     *
746     * @access private
747     * @return
748     */
749    public function scrClear() {
750        echo "\033[2J";
751    }
752
753    /**
754     * Prints a text at a specific screen/terminal coordinates
755     *
756     * @param int       $row        row number
757     * @param int       $col        column number
758     * @param string    $text       to be printed
759     *
760     * @access private
761     * @return
762     */
763    private function scrPrintAt($row, $col, $text="") {
764        echo "\033[".$row.";".$col."H".$text;
765    }
766
767}
768
769?>
Note: See TracBrowser for help on using the repository browser.