Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
  +----------------------------------------------------------------------+
4
  | PHP Version 4                                                        |
5
  +----------------------------------------------------------------------+
6
  | Copyright (c) 1997-2007 The PHP Group                                |
7
  +----------------------------------------------------------------------+
8
  | This source file is subject to version 2.02 of the PHP license,      |
9
  | that is bundled with this package in the file LICENSE, and is        |
10
  | available at through the world-wide-web at                           |
11
  | http://www.php.net/license/2_02.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
  | Author: Christian Dickmann <dickmann@php.net>                        |
17
  |         Tias Guns <tias@ulyssis.org>                                 |
18
  +----------------------------------------------------------------------+
19
 
20
 * @category   pear
21
 * @package    PEAR_Frontend_Web
22
 * @author     Christian Dickmann <dickmann@php.net>
23
 * @author     Tias Guns <tias@ulyssis.org>
24
 * @copyright  1997-2007 The PHP Group
25
 * @license    http://www.php.net/license/2_02.txt  PHP License 2.02
26
 * @version    CVS: $Id: Web.php 279136 2009-04-22 02:18:01Z saltybeagle $
27
 * @link       http://pear.php.net/package/PEAR_Frontend_Web
28
 * @since      File available since Release 0.1
29
 */
30
 
31
/**
32
 * base class
33
 */
34
require_once "PEAR.php";
35
require_once "PEAR/Config.php";
36
require_once "PEAR/Frontend.php";
37
require_once "HTML/Template/IT.php";
38
 
39
/**
40
 * PEAR_Frontend_Web is a HTML based Webfrontend for the PEAR Installer
41
 *
42
 * The Webfrontend provides basic functionality of the Installer, such as
43
 * a package list grouped by categories, a search mask, the possibility
44
 * to install/upgrade/uninstall packages and some minor things.
45
 * PEAR_Frontend_Web makes use of the PEAR::HTML_IT Template engine which
46
 * provides the possibillity to skin the Installer.
47
 *
48
 * @category   pear
49
 * @package    PEAR_Frontend_Web
50
 * @author     Christian Dickmann <dickmann@php.net>
51
 * @author     Tias Guns <tias@ulyssis.org>
52
 * @copyright  1997-2007 The PHP Group
53
 * @license    http://www.php.net/license/2_02.txt  PHP License 2.02
54
 * @version    CVS: $Id: Web.php 279136 2009-04-22 02:18:01Z saltybeagle $
55
 * @link       http://pear.php.net/package/PEAR_Frontend_Web
56
 * @since      File available since Release 0.1
57
 */
58
class PEAR_Frontend_Web extends PEAR_Frontend
59
{
60
    // {{{ properties
61
 
62
    /**
63
     * What type of user interface this frontend is for.
64
     * @var string
65
     * @access public
66
     */
67
    var $type = 'Web';
68
 
69
    /**
70
     * Container, where values can be saved temporary
71
     * @var array
72
     */
73
    var $_data = array();
74
 
75
    /**
76
     * Used to save output, to display it later
77
     */
78
    var $_savedOutput = array();
79
 
80
    /**
81
     * The config object
82
     */
83
    var $config;
84
 
85
    /**
86
     * List of packages that will not be deletable thourgh the webinterface
87
     */
88
    var $_no_delete_pkgs = array(
89
        'pear.php.net/Archive_Tar',
90
        'pear.php.net/Console_Getopt',
91
        'pear.php.net/HTML_Template_IT',
92
        'pear.php.net/PEAR',
93
        'pear.php.net/PEAR_Frontend_Web',
94
        'pear.php.net/Structures_Graph',
95
        'pear.php.net/XML_Util',
96
    );
97
 
98
    /**
99
     * List of channels that will not be deletable thourgh the webinterface
100
     */
101
    var $_no_delete_chans = array(
102
        'pear.php.net',
103
        '__uri',
104
        );
105
 
106
    /**
107
     * How many categories to display on one 'list-all' page
108
     */
109
    var $_paging_cats = 4;
110
 
111
    /**
112
     * Flag to determine whether to treat all output as information from a post-install script
113
     * @var bool
114
     */
115
    var $_installScript = false;
116
 
117
    // }}}
118
    // {{{ constructor
119
 
120
    function PEAR_Frontend_Web()
121
    {
122
        parent::PEAR();
123
        $this->config = &$GLOBALS['_PEAR_Frontend_Web_config'];
124
    }
125
 
126
    function setConfig(&$config)
127
    {
128
        $this->config = &$config;
129
    }
130
 
131
    // }}}
132
    // {{{ _initTemplate()
133
 
134
    /**
135
     * Initialize a TemplateObject
136
     *
137
     * @param string  $file     filename of the template file
138
     *
139
     * @return object Object of HTML/IT - Template - Class
140
     */
141
    function _initTemplate($file)
142
    {
143
        // Errors here can not be displayed using the UI
144
        PEAR::staticPushErrorHandling(PEAR_ERROR_DIE);
145
 
146
        $tpl_dir = $this->config->get('data_dir').DIRECTORY_SEPARATOR.'PEAR_Frontend_Web'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'templates';
147
        if (!file_exists($tpl_dir) || !is_readable($tpl_dir)) {
148
            PEAR::raiseError('<b>Error:</b> the template directory <i>('.$tpl_dir.')</i> is not a directory, or not readable. Make sure the \'data_dir\' of your config file <i>('.$this->config->get('data_dir').')</i> points to the correct location !');
149
        }
150
        $tpl = new HTML_Template_IT($tpl_dir);
151
        $tpl->loadTemplateFile($file);
152
        $tpl->setVariable("InstallerURL", $_SERVER["PHP_SELF"]);
153
 
154
        PEAR::staticPopErrorHandling(); // reset error handling
155
        return $tpl;
156
    }
157
 
158
    // }}}
159
    // {{{ displayError()
160
 
161
    /**
162
     * Display an error page
163
     *
164
     * @param mixed   $eobj  PEAR_Error object or string containing the error message
165
     * @param string  $title (optional) title of the page
166
     * @param string  $img   (optional) iconhandle for this page
167
     * @param boolean $popup (optional) popuperror or normal?
168
     *
169
     * @access public
170
     *
171
     * @return null does not return anything, but exit the script
172
     */
173
    function displayError($eobj, $title = 'Error', $img = 'error', $popup = false)
174
    {
175
        $msg = '';
176
        if (PEAR::isError($eobj)) {
177
            $msg .= trim($eobj->getMessage());
178
        } else {
179
            $msg .= trim($eobj);
180
        }
181
 
182
        $msg = nl2br($msg."\n");
183
 
184
        $tplfile = ($popup ? "error.popup.tpl.html" : "error.tpl.html");
185
        $tpl = $this->_initTemplate($tplfile);
186
 
187
        $tpl->setVariable("Error", $msg);
188
        $command_map = array(
189
            "install"   => "list",
190
            "uninstall" => "list",
191
            "upgrade"   => "list",
192
            );
193
        if (isset($_GET['command'])) {
194
            if (isset($command_map[$_GET['command']])) {
195
                $_GET['command'] = $command_map[$_GET['command']];
196
            }
197
            $tpl->setVariable("param", '?command='.$_GET['command']);
198
        }
199
 
200
        $tpl->show();
201
        exit;
202
    }
203
 
204
    // }}}
205
    // {{{ displayFatalError()
206
 
207
    /**
208
     * Alias for PEAR_Frontend_Web::displayError()
209
     *
210
     * @see PEAR_Frontend_Web::displayError()
211
     */
212
    function displayFatalError($eobj, $title = 'Error', $img = 'error')
213
    {
214
        $this->displayError($eobj, $title, $img);
215
    }
216
 
217
    // }}}
218
    // {{{ _outputListChannels()
219
 
220
    /**
221
     * Output the list of channels
222
     */
223
    function _outputListChannels($data)
224
    {
225
        $tpl = $this->_initTemplate('channel.list.tpl.html');
226
 
227
        $tpl->setVariable("Caption", $data['caption']);
228
 
229
        if (!isset($data['data'])) {
230
            $data['data'] = array();
231
        }
232
 
233
        $reg = &$this->config->getRegistry();
234
        foreach($data['data'] as $row) {
235
            list($channel, $summary) = $row;
236
            $url = sprintf('%s?command=channel-info&chan=%s',
237
                    $_SERVER['PHP_SELF'], urlencode($channel));
238
            $channel_info = sprintf('<a href="%s" class="blue">%s</a>', $url, $channel);
239
 
240
            // detect whether any packages from this channel are installed
241
            $anyinstalled = $reg->listPackages($channel);
242
            $id = 'id="'.$channel.'_href"';
243
            if (in_array($channel, $this->_no_delete_chans) || (is_array($anyinstalled) && count($anyinstalled))) {
244
                // dont delete
245
                $del = '&nbsp;';
246
            } else {
247
                $img = '<img src="'.$_SERVER["PHP_SELF"].'?img=uninstall" width="18" height="17"  border="0" alt="delete">';
248
                $url = sprintf('%s?command=channel-delete&chan=%s',
249
                    $_SERVER["PHP_SELF"], urlencode($channel));
250
                $del = sprintf('<a href="%s" onClick="return deleteChan(\'%s\');" %s >%s</a>',
251
                    $url, $channel, $id, $img);
252
            }
253
 
254
            $tpl->setCurrentBlock("Row");
255
            $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package');
256
            $tpl->setVariable("UpdateChannelsURL", $_SERVER['PHP_SELF']);
257
            $tpl->setVariable("Delete", $del);
258
            $tpl->setVariable("Channel", $channel_info);
259
            $tpl->setVariable("Summary", nl2br($summary));
260
            $tpl->parseCurrentBlock();
261
        }
262
        $tpl->show();
263
        return true;
264
    }
265
 
266
    // }}}
267
    // {{{ _outputListAll()
268
 
269
    /**
270
     * Output a list of packages, grouped by categories. Uses Paging
271
     *
272
     * @param array   $data     array containing all data to display the list
273
     * @param boolean $paging   (optional) use Paging or not
274
     *
275
     * @return boolean true (yep. i am an optimist)
276
     *
277
     * DEPRECATED BY list-categories
278
     */
279
    function _outputListAll($data, $paging=true)
280
    {
281
        if (!isset($data['data'])) {
282
            return true;
283
        }
284
 
285
        $tpl = $this->_initTemplate('package.list.tpl.html');
286
        $tpl->setVariable('Caption', $data['caption']);
287
 
288
        if (!is_array($data['data'])) {
289
            $tpl->show();
290
            print('<p><table><tr><td width="50">&nbsp;</td><td>'.$data['data'].'</td></tr></table></p>');
291
            return true;
292
        }
293
 
294
        $command = isset($_GET['command']) ? $_GET['command']:'list-all';
295
        $mode = isset($_GET['mode'])?$_GET['mode']:'';
296
        $links = array('back' => '',
297
                       'next' => '',
298
                       'current' => '&mode='.$mode,
299
                       );
300
 
301
        if ($paging) {
302
            // Generate Linkinformation to redirect to _this_ page after performing an action
303
            $link_str = '<a href="?command=%s&from=%s&mode=%s" class="paging_link">%s</a>';
304
 
305
            $pageId = isset($_GET['from']) ? $_GET['from'] : 0;
306
            $paging_data = $this->__getData($pageId, $this->_paging_cats, count($data['data']), false);
307
            $data['data'] = array_slice($data['data'], $pageId, $this->_paging_cats);
308
            $from = $paging_data['from'];
309
            $to = $paging_data['to'];
310
 
311
            if ($paging_data['from']>1) {
312
                $links['back'] = sprintf($link_str, $command, $paging_data['prev'], $mode, '&lt;&lt;');
313
            }
314
 
315
            if ( $paging_data['next']) {
316
                $links['next'] = sprintf($link_str, $command, $paging_data['next'], $mode, '&gt;&gt;');
317
            }
318
 
319
            $links['current'] = '&from=' . $paging_data['from'];
320
 
321
            $blocks = array('Paging_pre', 'Paging_post');
322
            foreach ($blocks as $block) {
323
                $tpl->setCurrentBlock($block);
324
                $tpl->setVariable('Prev', $links['back']);
325
                $tpl->setVariable('Next', $links['next']);
326
                $tpl->setVariable('PagerFrom', $from);
327
                $tpl->setVariable('PagerTo', $to);
328
                $tpl->setVariable('PagerCount', $paging_data['numrows']);
329
                $tpl->parseCurrentBlock();
330
            }
331
        }
332
 
333
        $reg = &$this->config->getRegistry();
334
        foreach($data['data'] as $category => $packages) {
335
            foreach($packages as $row) {
336
                list($pkgChannel, $pkgName, $pkgVersionLatest, $pkgVersionInstalled, $pkgSummary) = $row;
337
                $parsed = $reg->parsePackageName($pkgName, $pkgChannel);
338
                $pkgChannel = $parsed['channel'];
339
                $pkgName = $parsed['package'];
340
                $pkgFull = sprintf('%s/%s-%s',
341
                            $pkgChannel,
342
                            $pkgName,
343
                            substr($pkgVersionLatest, 0, strpos($pkgVersionLatest, ' ')));
344
                $tpl->setCurrentBlock("Row");
345
                $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package');
346
                $images = array(
347
                    'install' => '<img src="'.$_SERVER["PHP_SELF"].'?img=install" width="13" height="13" border="0" alt="install">',
348
                    'uninstall' => '<img src="'.$_SERVER["PHP_SELF"].'?img=uninstall" width="18" height="17"  border="0" alt="uninstall">',
349
                    'upgrade' => '<img src="'.$_SERVER["PHP_SELF"].'?img=install" width="13" height="13" border="0" alt="upgrade">',
350
                    'info' => '<img src="'.$_SERVER["PHP_SELF"].'?img=info"  width="17" height="19" border="0" alt="info">',
351
                    'infoExt' => '<img src="'.$_SERVER["PHP_SELF"].'?img=infoplus"  width="18" height="19" border="0" alt="extended info">',
352
                    );
353
                $urls   = array(
354
                    'install' => sprintf('%s?command=install&pkg=%s%s',
355
                        $_SERVER["PHP_SELF"], $pkgFull, $links['current']),
356
                    'uninstall' => sprintf('%s?command=uninstall&pkg=%s%s',
357
                        $_SERVER["PHP_SELF"], $pkgFull, $links['current']),
358
                    'upgrade' => sprintf('%s?command=upgrade&pkg=%s%s',
359
                        $_SERVER["PHP_SELF"], $pkgFull, $links['current']),
360
                    'info' => sprintf('%s?command=info&pkg=%s',
361
                        $_SERVER["PHP_SELF"], $pkgFull),
362
                    'remote-info' => sprintf('%s?command=remote-info&pkg=%s',
363
                        $_SERVER["PHP_SELF"], $pkgFull),
364
                    'infoExt' => 'http://' . $this->config->get('preferred_mirror').'/package/'.$pkgName,
365
                    );
366
 
367
                $compare = version_compare($pkgVersionLatest, $pkgVersionInstalled);
368
                $id = 'id="'.$pkgName.'_href"';
369
                if (!$pkgVersionInstalled || $pkgVersionInstalled == "- no -") {
370
                    $inst = sprintf('<a href="%s" onClick="return installPkg(\'%s\');" %s>%s</a>',
371
                        $urls['install'], $pkgName, $id, $images['install']);
372
                    $del = '';
373
                    $info = sprintf('<a href="%s">%s</a>', $urls['remote-info'],    $images['info']);
374
                } else if ($compare == 1) {
375
                    $inst = sprintf('<a href="%s" onClick="return installPkg(\'%s\');" %s>%s</a>',
376
                        $urls['upgrade'], $pkgName, $id, $images['upgrade']);
377
                    $del = sprintf('<a href="%s" onClick="return uninstallPkg(\'%s\');" %s >%s</a>',
378
                        $urls['uninstall'], $pkgName, $id, $images['uninstall']);
379
                    $info = sprintf('<a href="%s">%s</a>', $urls['info'],    $images['info']);
380
                } else {
381
                    $inst = '';
382
                    $del = sprintf('<a href="%s" onClick="return uninstallPkg(\'%s\');" %s >%s</a>',
383
                        $urls['uninstall'], $pkgName, $id, $images['uninstall']);
384
                    $info = sprintf('<a href="%s">%s</a>', $urls['info'],    $images['info']);
385
                }
386
                $infoExt = sprintf('<a href="%s">%s</a>', $urls['infoExt'], $images['infoExt']);
387
 
388
                if (in_array($pkgChannel.'/'.$pkgName, $this->_no_delete_pkgs)) {
389
                    $del = '';
390
                }
391
 
392
                $tpl->setVariable("Latest", $pkgVersionLatest);
393
                $tpl->setVariable("Installed", $pkgVersionInstalled);
394
                $tpl->setVariable("Install", $inst);
395
                $tpl->setVariable("Delete", $del);
396
                $tpl->setVariable("Info", $info);
397
                $tpl->setVariable("InfoExt", $infoExt);
398
                $tpl->setVariable("Package", $pkgName);
399
                $tpl->setVariable("Channel", $pkgChannel);
400
                $tpl->setVariable("Summary", nl2br($pkgSummary));
401
                $tpl->parseCurrentBlock();
402
            }
403
            $tpl->setCurrentBlock("Category");
404
            $tpl->setVariable("categoryName", $category);
405
            $tpl->setVariable("ImgCategory", $_SERVER["PHP_SELF"].'?img=category');
406
            $tpl->parseCurrentBlock();
407
        }
408
        $tpl->show();
409
 
410
        return true;
411
    }
412
 
413
    // }}}
414
    // {{{ _outputListFiles()
415
 
416
    /**
417
     * Output a list of files of a packagename
418
     *
419
     * @param array $data array containing all files of a package
420
     *
421
     * @return boolean true (yep. i am an optimist)
422
     */
423
    function _outputListFiles($data)
424
    {
425
        sort($data['data']);
426
        return $this->_outputGenericTableVertical($data['caption'], $data['data']);
427
    }
428
 
429
    // }}}
430
    // {{{ _outputListDocs()
431
 
432
    /**
433
     * Output a list of documentation files of a packagename
434
     *
435
     * @param array $data array containing all documentation files of a package
436
     *
437
     * @return boolean true (yep. i am an optimist)
438
     */
439
    function _outputListDocs($data)
440
    {
441
        $tpl = $this->_initTemplate('caption.tpl.html');
442
        $tpl->setVariable('Caption', $data['caption']);
443
        $tpl->show();
444
 
445
        if (is_array($data['data'])) {
446
            print $this->_getListDocsDiv($data['channel'].'/'.$data['package'], $data['data']);
447
        } else {
448
            print $data['data'];
449
        }
450
        return true;
451
    }
452
 
453
    /**
454
     * Get list of the docs of a package in a HTML div
455
     *
456
     * @param string $pkg full package name (channel/package)
457
     * @param array $files array of all files and there location
458
     * @return string HTML
459
     */
460
    function _getListDocsDiv($pkg, $files) {
461
        $out = '<div id="listdocs"><ul>';
462
        foreach($files as $name => $location) {
463
            $out .= sprintf('<li><a href="%s?command=doc-show&pkg=%s&file=%s" title="%s">%s</a></li>',
464
                    $_SERVER['PHP_SELF'],
465
                    $pkg,
466
                    urlencode($name),
467
                    $location,
468
                    $name);
469
        }
470
        $out .= '</ul></div>';
471
 
472
        return $out;
473
    }
474
 
475
    // }}}
476
    // {{{ _outputDocShow()
477
 
478
    /**
479
     * Output a documentation file of a packagename
480
     *
481
     * @param array $data array containing all documentation files of a packages
482
     *
483
     * @return boolean true (yep. i am an optimist)
484
     */
485
    function _outputDocShow($data)
486
    {
487
        $tpl = $this->_initTemplate('caption.tpl.html');
488
        $tpl->setVariable('Caption', $data['caption']);
489
        $tpl->show();
490
 
491
        print '<div id="docshow">'.nl2br(htmlentities($data['data'])).'</div>';
492
        return true;
493
    }
494
 
495
    // }}}
496
    // {{{ _outputListPackages()
497
 
498
    /**
499
     * Output packagenames (of a channel or category)
500
     *
501
     * @param array $data array containing all information about the packages
502
     *
503
     * @return boolean true (yep. i am an optimist)
504
     */
505
    function _outputListPackages($data)
506
    {
507
        $ROWSPAN=3;
508
 
509
        $caption = sprintf('<a name="%s"><img src="%s?img=category" /> %s (%s)</a>',
510
                            $data['channel'],
511
                            $_SERVER['PHP_SELF'],
512
                            $data['caption'],
513
                            count($data['data']));
514
 
515
        $newdata = null;
516
        if (!is_array($data['data'])) {
517
            $newdata = $data['data'];
518
        } else {
519
            $newdata = array(0 => array());
520
            $row = 0;
521
            $col = 0;
522
            $rows = ceil(count($data['data'])/$ROWSPAN);
523
            foreach ($data['data'] as $package) {
524
                if ($row == $rows) { // row is full
525
                    $row = 0;
526
                    $col++;
527
                }
528
                if ($col == 0) { // create clean arrays
529
                    $newdata[$row] = array();
530
                }
531
                $newdata[$row][$col] = sprintf('<img src="%s?img=package" /> <a href="%s?command=info&pkg=%s/%s" class="blue">%s</a>',
532
                                $_SERVER['PHP_SELF'],
533
                                $_SERVER['PHP_SELF'],
534
                                $package[0],
535
                                $package[1],
536
                                $package[1]);
537
                $row++;
538
            }
539
            while ($row != $rows) {
540
                $newdata[$row][$col] = '&nbsp;';
541
                $row++;
542
            }
543
        }
544
 
545
        return $this->_outputGenericTableHorizontal($caption, $newdata);
546
    }
547
 
548
    // }}}
549
    // {{{ _outputListCategories()
550
 
551
    /**
552
     * Prepare output per channel/category
553
     *
554
     * @param array   $data     array containing caption, channel and headline
555
     *
556
     * @return $tpl Template Object
557
     */
558
    function _prepareListCategories($data)
559
    {
560
        $channel = $data['channel'];
561
 
562
        if (!is_array($data['data']) && $channel == '__uri') {
563
            // no categories in __uri, don't show this ugly duck !
564
            return true;
565
        }
566
 
567
        $tpl = $this->_initTemplate('categories.list.tpl.html');
568
 
569
        $tpl->setVariable('categoryName', $data['caption']);
570
        $tpl->setVariable('channel', $data['channel']);
571
 
572
        // set headlines
573
        if (isset($data['headline']) && is_array($data['headline'])) {
574
            foreach($data['headline'] as $text) {
575
                $tpl->setCurrentBlock('Headline');
576
                $tpl->setVariable('Text', $text);
577
                $tpl->parseCurrentBlock();
578
            }
579
        } else {
580
            $tpl->setCurrentBlock('Headline');
581
            $tpl->setVariable('Text', $data['data']);
582
            $tpl->parseCurrentBlock();
583
            unset($data['data']); //clear
584
        }
585
 
586
        // set extra title info
587
        $tpl->setCurrentBlock('Title_info');
588
        $info = sprintf('<a href="%s?command=list-packages&chan=%s" class="green">List all packagenames of this channel.</a>',
589
                        $_SERVER['PHP_SELF'],
590
                        $channel
591
                            );
592
        $tpl->setVariable('Text', $info);
593
        $tpl->parseCurrentBlock();
594
 
595
        $tpl->setCurrentBlock('Title_info');
596
        $info = sprintf('<a href="%s?command=list-categories&chan=%s&opt=packages" class="green">List all packagenames, by category, of this channel.</a>',
597
                        $_SERVER['PHP_SELF'],
598
                        $channel
599
                            );
600
        $tpl->setVariable('Text', $info);
601
        $tpl->parseCurrentBlock();
602
 
603
        return $tpl;
604
    }
605
 
606
    /**
607
     * Output the list of categories of a channel
608
     *
609
     * @param array   $data     array containing all data to display the list
610
     *
611
     * @return boolean true (yep. i am an optimist)
612
     */
613
    function _outputListCategories($data)
614
    {
615
        $tpl = $this->_prepareListCategories($data);
616
 
617
        if (isset($data['data']) && is_array($data['data'])) {
618
            foreach($data['data'] as $row) {
619
                @list($channel, $category, $packages) = $row;
620
 
621
                $tpl->setCurrentBlock('Data_row');
622
                $tpl->setVariable('Text', $channel);
623
                $tpl->parseCurrentBlock();
624
 
625
                $tpl->setCurrentBlock('Data_row');
626
                $info = sprintf('<a href="%s?command=list-category&chan=%s&cat=%s" class="green">%s</a>',
627
                            $_SERVER['PHP_SELF'],
628
                            $channel,
629
                            $category,
630
                            $category
631
                                );
632
                $tpl->setVariable('Text', $info);
633
                $tpl->parseCurrentBlock();
634
 
635
                if (is_array($packages)) {
636
                    if (count($packages) == 0) {
637
                        $info = '<i>(no packages registered)</i>';
638
                    } else {
639
                        $info = sprintf('<img src="%s?img=package" />: ',
640
                                $_SERVER['PHP_SELF']);
641
                    }
642
                    foreach($packages as $i => $package) {
643
                        $info .= sprintf('<a href="%s?command=info&pkg=%s/%s" class="blue">%s</a>',
644
                                    $_SERVER['PHP_SELF'],
645
                                    $channel,
646
                                    $package,
647
                                    $package
648
                                        );
649
 
650
                        if ($i+1 != count($packages)) {
651
                            $info .= ', ';
652
                        }
653
                    }
654
                    $tpl->setCurrentBlock('Data_row');
655
                    $tpl->setVariable('Text', $info);
656
                    $tpl->parseCurrentBlock();
657
                }
658
 
659
                $tpl->setCurrentBlock('Data');
660
                $tpl->setVariable('Img', 'category');
661
                $tpl->parseCurrentBlock();
662
            }
663
        }
664
 
665
        $tpl->show();
666
 
667
        return true;
668
    }
669
 
670
    /**
671
     * Output the list of packages of a category of a channel
672
     *
673
     * @param array   $data     array containing all data to display the list
674
     *
675
     * @return boolean true (yep. i am an optimist)
676
     */
677
    function _outputListCategory($data)
678
    {
679
        if (isset($data['headline'])) {
680
            // create place for install/uninstall icon:
681
            $summary = array_pop($data['headline']);
682
            $data['headline'][] = '&nbsp;'; // icon
683
            $data['headline'][] = $summary; // restore summary
684
        }
685
        $tpl = $this->_prepareListCategories($data);
686
        $channel = $data['channel'];
687
 
688
        if (isset($data['data']) && is_array($data['data'])) {
689
            foreach($data['data'] as $row) {
690
                // output summary after install icon
691
                $summary = array_pop($row);
692
 
693
                foreach ($row as $i => $col) {
694
                    if ($i == 1) {
695
                        $package = $col;
696
                        // package name, make URL
697
                        $col = $this->_prepPkgName($package, $channel);
698
                    }
699
 
700
                    $tpl->setCurrentBlock('Data_row');
701
                    $tpl->setVariable('Text', $col);
702
                    $tpl->parseCurrentBlock();
703
                }
704
 
705
                // install or uninstall icon
706
                $tpl->setCurrentBlock('Data_row');
707
                $tpl->setVariable('Text', $this->_prepIcons($package, $channel));
708
                $tpl->parseCurrentBlock();
709
 
710
                // now the summary
711
                $tpl->setCurrentBlock('Data_row');
712
                $tpl->setVariable('Text', $summary);
713
                $tpl->parseCurrentBlock();
714
 
715
                // and finish.
716
                $tpl->setCurrentBlock('Data');
717
                $tpl->setVariable('Img', 'package');
718
                $tpl->parseCurrentBlock();
719
            }
720
        }
721
 
722
        $tpl->show();
723
 
724
        return true;
725
    }
726
 
727
    // }}}
728
    // {{{ _outputList()
729
 
730
    /**
731
     * Output the list of installed packages.
732
     *
733
     * @param array   $data     array containing all data to display the list
734
     *
735
     * @return boolean true (yep. i am an optimist)
736
     */
737
    function _outputList($data)
738
    {
739
        $channel = $data['channel'];
740
 
741
        if (!is_array($data['data']) && $channel == '__uri') {
742
            // no packages in __uri, don't show this ugly duck !
743
            return true;
744
        }
745
 
746
        $tpl = $this->_initTemplate('package.list_nocat.tpl.html');
747
 
748
        $tpl->setVariable('categoryName', $data['caption']);
749
        //$tpl->setVariable('Border', $data['border']);
750
 
751
        // set headlines
752
        if (isset($data['headline']) && is_array($data['headline'])) {
753
            // overwrite
754
            $data['headline'] = array('Channel', 'Package', 'Local', '&nbsp;', 'Summary');
755
            foreach($data['headline'] as $text) {
756
                $tpl->setCurrentBlock('Headline');
757
                $tpl->setVariable('Text', $text);
758
                $tpl->parseCurrentBlock();
759
            }
760
        } else {
761
            $tpl->setCurrentBlock('Headline');
762
            if (is_array($data['data']) && isset($data['data'][0])) {
763
                $tpl->setVariable('Text', $data['data'][0][0]);
764
            } else {
765
                $tpl->setVariable('Text', $data['data']);
766
            }
767
            $tpl->parseCurrentBlock();
768
            unset($data['data']); //clear
769
        }
770
 
771
        if (isset($data['data']) && is_array($data['data'])) {
772
            foreach($data['data'] as $row) {
773
                $package = $row[0].'/'.$row[1];
774
                $package_name = $row[1];
775
                $local = sprintf('%s (%s)', $row[2], $row[3]);
776
 
777
                // Channel
778
                $tpl->setCurrentBlock('Data_row');
779
                $tpl->setVariable('Text', $channel);
780
                $tpl->parseCurrentBlock();
781
 
782
                // Package
783
                $tpl->setCurrentBlock('Data_row');
784
                $tpl->setVariable('Text', $this->_prepPkgName($package_name, $channel));
785
                $tpl->parseCurrentBlock();
786
 
787
                // Local
788
                $tpl->setCurrentBlock('Data_row');
789
                $tpl->setVariable('Text', $local);
790
                $tpl->parseCurrentBlock();
791
 
792
                // Icons (uninstall)
793
                $tpl->setCurrentBlock('Data_row');
794
                $tpl->setVariable('Text', $this->_prepIcons($package_name, $channel, true));
795
                $tpl->parseCurrentBlock();
796
 
797
                // Summary
798
                $tpl->setCurrentBlock('Data_row');
799
                $reg = $this->config->getRegistry();
800
                $tpl->setVariable('Text', $reg->packageInfo($package_name, 'summary', $channel));
801
                $tpl->parseCurrentBlock();
802
 
803
                // and finish.
804
                $tpl->setCurrentBlock('Data');
805
                $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package');
806
                $tpl->parseCurrentBlock();
807
            }
808
        }
809
 
810
        $tpl->show();
811
 
812
        return true;
813
    }
814
 
815
    // }}}
816
    // {{{ _outputListUpgrades()
817
 
818
    /**
819
     * Output the list of available upgrades packages.
820
     *
821
     * @param array   $data     array containing all data to display the list
822
     *
823
     * @return boolean true (yep. i am an optimist)
824
     */
825
    function _outputListUpgrades($data)
826
    {
827
        $tpl = $this->_initTemplate('package.list_nocat.tpl.html');
828
 
829
        $tpl->setVariable('categoryName', $data['caption']);
830
        //$tpl->setVariable('Border', $data['border']);
831
 
832
 
833
        $channel = $data['channel'];
834
 
835
        // set headlines
836
        if (isset($data['headline']) && is_array($data['headline'])) {
837
            $data['headline'][] = '&nbsp;';
838
            foreach($data['headline'] as $text) {
839
                $tpl->setCurrentBlock('Headline');
840
                $tpl->setVariable('Text', $text);
841
                $tpl->parseCurrentBlock();
842
            }
843
        } else {
844
            $tpl->setCurrentBlock('Headline');
845
            $tpl->setVariable('Text', $data['data']);
846
            $tpl->parseCurrentBlock();
847
            unset($data['data']); //clear
848
        }
849
 
850
        if (isset($data['data']) && is_array($data['data'])) {
851
            foreach($data['data'] as $row) {
852
                $package = $channel.'/'.$row[1];
853
                $package_name = $row[1];
854
 
855
                foreach($row as $i => $text) {
856
                    if ($i == 1) {
857
                        // package name
858
                        $text = $this->_prepPkgName($text, $channel);
859
                    }
860
                    $tpl->setCurrentBlock('Data_row');
861
                    $tpl->setVariable('Text', $text);
862
                    $tpl->parseCurrentBlock();
863
                }
864
                // upgrade link
865
                $tpl->setCurrentBlock('Data_row');
866
                $img = sprintf('<img src="%s?img=install" width="18" height="17"  border="0" alt="upgrade">', $_SERVER["PHP_SELF"]);
867
                $url = sprintf('%s?command=upgrade&pkg=%s', $_SERVER["PHP_SELF"], $package);
868
                $text = sprintf('<a href="%s" onClick="return installPkg(\'%s\');" id="%s">%s</a>', $url, $package, $package.'_href', $img);
869
                $tpl->setVariable('Text', $text);
870
                $tpl->parseCurrentBlock();
871
 
872
                // and finish.
873
                $tpl->setCurrentBlock('Data');
874
                $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package');
875
 
876
                $tpl->parseCurrentBlock();
877
            }
878
        }
879
 
880
        $tpl->show();
881
 
882
        return true;
883
    }
884
 
885
    // }}}
886
 
887
    function _getPackageDeps($deps)
888
    {
889
        if (count($deps) == 0) {
890
            return "<i>No dependencies registered.</i>\n";
891
        } else {
892
            $rel_trans = array(
893
                'lt' => 'older than %s',
894
                'le' => 'version %s or older',
895
                'eq' => 'version %s',
896
                'ne' => 'any version but %s',
897
                'gt' => 'newer than %s',
898
                'ge' => '%s or newer',
899
                );
900
            $dep_type_desc = array(
901
                'pkg'    => 'PEAR Package',
902
                'ext'    => 'PHP Extension',
903
                'php'    => 'PHP Version',
904
                'prog'   => 'Program',
905
                'ldlib'  => 'Development Library',
906
                'rtlib'  => 'Runtime Library',
907
                'os'     => 'Operating System',
908
                'websrv' => 'Web Server',
909
                'sapi'   => 'SAPI Backend',
910
                );
911
            $result = "      <dl>\n";
912
            foreach($deps as $row) {
913
 
914
                // Print link if it's a PEAR package
915
                if ($row['type'] == 'pkg') {
916
                    $package = $row['channel'].'/'.$row['name'];
917
                    $row['name'] = sprintf('<a class="green" href="%s?command=remote-info&pkg=%s">%s</a>',
918
                        $_SERVER['PHP_SELF'], $package, $package);
919
                }
920
 
921
                if (isset($rel_trans[$row['rel']])) {
922
                    $rel = sprintf($rel_trans[$row['rel']], $row['version']);
923
                    $optional = isset($row['optional']) && $row['optional'] == 'yes';
924
                    $result .= sprintf("%s: %s %s" . $optional,
925
                           $dep_type_desc[$row['type']], @$row['name'], $rel);
926
                } else {
927
                    $result .= sprintf("%s: %s", $dep_type_desc[$row['type']], $row['name']);
928
                }
929
                $result .= '<br>';
930
            }
931
            $result .= "      </dl>\n";
932
        }
933
        return $result;
934
    }
935
 
936
    /**
937
     * Output details of one package, info (local)
938
     *
939
     * @param array $data array containing all information about the package
940
     *
941
     * @return boolean true (yep. i am an optimist)
942
     */
943
    function _outputPackageInfo($data)
944
    {
945
        $data['data'] = $this->htmlentities_recursive($data['data']);
946
        if (!isset($data['raw']['channel'])) {
947
            // package1.xml, channel by default pear
948
            $channel = 'pear.php.net';
949
            $package_name = $data['raw']['package'];
950
        } else {
951
            $channel = $data['raw']['channel'];
952
            $package_name = $data['raw']['name'];
953
        }
954
        $package = $channel.'/'.$package_name;
955
 
956
        // parse extra options
957
        if (!in_array($package, $this->_no_delete_pkgs)) {
958
            $image = sprintf('<img src="%s?img=uninstall" width="18" height="17"  border="0" alt="uninstall">', $_SERVER["PHP_SELF"]);
959
            $output = sprintf(
960
                    '<a href="%s?command=uninstall&pkg=%s" class="green" %s>%s Uninstall package</a>',
961
                    $_SERVER["PHP_SELF"],
962
                    $package,
963
                    'onClick="return uninstallPkg(\''.$package.'\');"',
964
                    $image);
965
            $data['data'][] = array('Options', $output);
966
        }
967
 
968
        $output = '';
969
        // More: Local Documentation
970
        require_once('PEAR/Frontend/Web/Docviewer.php');
971
        if (count(PEAR_Frontend_Web_Docviewer::getDocFiles($package_name, $channel)) !== 0) {
972
            $image = sprintf('<img src="%s?img=manual" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
973
            $output .= sprintf(
974
                    '<a href="%s?command=list-docs&pkg=%s" class="green">%s Package Documentation</a>',
975
                    $_SERVER["PHP_SELF"],
976
                    $package,
977
                    $image);
978
            $output .= '<br />';
979
        }
980
        $output .= sprintf(
981
                    '<a href="%s?command=list-files&pkg=%s" class="green">./.. List Files</a>',
982
                    $_SERVER["PHP_SELF"],
983
                    $package);
984
        $output .= '<br />';
985
        // More: Extended Package Information
986
        $image = sprintf('<img src="%s?img=infoplus" border="0" alt="extra info">', $_SERVER["PHP_SELF"]);
987
        if ($channel == 'pear.php.net' || $channel == 'pecl.php.net') {
988
            $url = 'http://%s/package/%s/download/%s';
989
        } else {
990
            // the normal default
991
            $url = 'http://%s/index.php?package=%s&release=%s';
992
        }
993
        $output .= sprintf(
994
                    '<a href="'.$url.'" class="green" target="_new">%s Extended Package Information</a>',
995
                    $this->config->get('preferred_mirror', null, $channel),
996
                    $package_name,
997
                    $data['raw']['version']['release'],
998
                    $image);
999
        // More: Developer Documentation && Package Manual
1000
        if ($channel == 'pear.php.net') {
1001
            $output .= '<br />';
1002
            $image = sprintf('<img src="%s?img=manualplus" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1003
            $output .= sprintf(
1004
                        '<a href="http://pear.php.net/package/%s/docs/latest" class="green" target="_new">%s pear.php.net Developer Documentation</a>',
1005
                        $package_name,
1006
                        $image);
1007
            $output .= '<br />';
1008
            $image = sprintf('<img src="%s?img=manualplus" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1009
            $output .= sprintf(
1010
                        '<a href="http://pear.php.net/manual/en/" class="green" target="_new">%s pear.php.net Package Manual </a>',
1011
                        $image);
1012
        }
1013
        $data['data'][] = array('More', $output);
1014
 
1015
        return $this->_outputGenericTableVertical($data['caption'], $data['data']);
1016
    }
1017
 
1018
    /**
1019
     * Output details of one package, remote-info
1020
     *
1021
     * @param array $data array containing all information about the package
1022
     *
1023
     * @return boolean true (yep. i am an optimist)
1024
     */
1025
    function _outputPackageRemoteInfo($data)
1026
    {
1027
        include_once "PEAR/Downloader.php";
1028
        $tpl = $this->_initTemplate('package.info.tpl.html');
1029
 
1030
        $tpl->setVariable("PreferredMirror", $this->config->get('preferred_mirror'));
1031
        /*
1032
        $dl = &new PEAR_Downloader($this, array(), $this->config);
1033
        // don't call private functions
1034
        // gives error, not gonna fix, but gonna skip
1035
        $info = $dl->_getPackageDownloadUrl(array('package' => $data['name'],
1036
            'channel' => $this->config->get('default_channel'), 'version' => $data['stable']));
1037
        if (isset($info['url'])) {
1038
            $tpl->setVariable("DownloadURL", $info['url']);
1039
        } else {
1040
            $tpl->setVariable("DownloadURL", $_SERVER['PHP_SELF']);
1041
        }
1042
        */
1043
        $channel = $data['channel'];
1044
        $package = $data['channel'].'/'.$data['name'];
1045
        $package_full = $data['channel'].'/'.$data['name'].'-'.$data['stable'];
1046
 
1047
        $tpl->setVariable("Latest", $data['stable']);
1048
        $tpl->setVariable("Installed", $data['installed']);
1049
        $tpl->setVariable("Package", $data['name']);
1050
        $tpl->setVariable("License", $data['license']);
1051
        $tpl->setVariable("Category", $data['category']);
1052
        $tpl->setVariable("Summary", nl2br($data['summary']));
1053
        $tpl->setVariable("Description", nl2br($data['description']));
1054
        $deps = @$data['releases'][$data['stable']]['deps'];
1055
        $tpl->setVariable("Dependencies", $this->_getPackageDeps($deps));
1056
 
1057
        $compare = version_compare($data['stable'], $data['installed']);
1058
 
1059
        $images = array(
1060
            'install' => '<img src="'.$_SERVER["PHP_SELF"].'?img=install" width="13" height="13" border="0" alt="install">',
1061
            'uninstall' => '<img src="'.$_SERVER["PHP_SELF"].'?img=uninstall" width="18" height="17"  border="0" alt="uninstall">',
1062
            'upgrade' => '<img src="'.$_SERVER["PHP_SELF"].'?img=install" width="13" height="13" border="0" alt="upgrade">',
1063
            );
1064
 
1065
        $opt_img = array();
1066
        $opt_text = array();
1067
        if (!$data['installed'] || $data['installed'] == "- no -") {
1068
            $opt_img[] = sprintf(
1069
                '<a href="%s?command=install&pkg=%s" %s>%s</a>',
1070
                $_SERVER["PHP_SELF"], $package_full,
1071
                'onClick="return installPkg(\''.$package_full.'\');"',
1072
                $images['install']);
1073
            $opt_text[] = sprintf(
1074
                '<a href="%s?command=install&pkg=%s" class="green" %s>Install package</a>',
1075
                $_SERVER["PHP_SELF"], $package_full,
1076
                'onClick="return installPkg(\''.$package_full.'\');"');
1077
        } else if ($compare == 1) {
1078
            $opt_img[] = sprintf(
1079
                '<a href="%s?command=upgrade&pkg=%s" %s>%s</a><br>',
1080
                $_SERVER["PHP_SELF"], $package,
1081
                'onClick="return installPkg(\''.$package.'\');"',
1082
                $images['install']);
1083
            $opt_text[] = sprintf(
1084
                '<a href="%s?command=upgrade&pkg=%s" class="green" %s>Upgrade package</a>',
1085
                $_SERVER["PHP_SELF"], $package,
1086
                'onClick="return installPkg(\''.$package.'\');"');
1087
            if (!in_array($package, $this->_no_delete_pkgs)) {
1088
                $opt_img[] = sprintf(
1089
                    '<a href="%s?command=uninstall&pkg=%s" %s>%s</a>',
1090
                    $_SERVER["PHP_SELF"], $package,
1091
                    'onClick="return uninstallPkg(\''.$package.'\');"',
1092
                    $images['uninstall']);
1093
                $opt_text[] = sprintf(
1094
                    '<a href="%s?command=uninstall&pkg=%s" class="green" %s>Uninstall package</a>',
1095
                    $_SERVER["PHP_SELF"], $package,
1096
                    'onClick="return uninstallPkg(\''.$package.'\');"');
1097
           }
1098
        } else {
1099
            if (!in_array($package, $this->_no_delete_pkgs)) {
1100
                $opt_img[] = sprintf(
1101
                    '<a href="%s?command=uninstall&pkg=%s" %s>%s</a>',
1102
                    $_SERVER["PHP_SELF"], $package,
1103
                    'onClick="return uninstallPkg(\''.$package.'\');"',
1104
                    $images['uninstall']);
1105
                $opt_text[] = sprintf(
1106
                    '<a href="%s?command=uninstall&pkg=%s" class="green" %s>Uninstall package</a>',
1107
                    $_SERVER["PHP_SELF"], $package,
1108
                    'onClick="return uninstallPkg(\''.$package.'\');"');
1109
           }
1110
        }
1111
 
1112
        if (isset($opt_img[0]))
1113
        {
1114
            $tpl->setVariable('Opt_Img_1', $opt_img[0]);
1115
            $tpl->setVariable('Opt_Text_1', $opt_text[0]);
1116
        }
1117
        if (isset($opt_img[1]))
1118
        {
1119
            $tpl->setVariable('Opt_Img_2', $opt_img[1]);
1120
            $tpl->setVariable('Opt_Text_2', $opt_text[1]);
1121
        }
1122
 
1123
        $tpl->setVariable('More_Title', 'More');
1124
        // More: Extended Package Information
1125
        $image = sprintf('<img src="%s?img=infoplus" border="0" alt="extra info">', $_SERVER["PHP_SELF"]);
1126
        if ($channel == 'pear.php.net' || $channel == 'pecl.php.net') {
1127
            $url = 'http://%s/package/%s/download/%s';
1128
        } else {
1129
            // the normal default
1130
            $url = 'http://%s/index.php?package=%s&release=%s';
1131
        }
1132
        $output = sprintf(
1133
                    '<a href="'.$url.'" class="green" target="_new">%s Extended Package Information</a>',
1134
                    $this->config->get('preferred_mirror', null, $channel),
1135
                    $data['name'],
1136
                    $data['stable'],
1137
                    $image);
1138
        // More: Developer Documentation && Package Manual
1139
        if ($channel == 'pear.php.net') {
1140
            $output .= '<br />';
1141
            $image = sprintf('<img src="%s?img=manualplus" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1142
            $output .= sprintf(
1143
                        '<a href="http://pear.php.net/package/%s/docs/latest" class="green" target="_new">%s pear.php.net Developer Documentation</a>',
1144
                        $data['name'],
1145
                        $image);
1146
            $output .= '<br />';
1147
            $image = sprintf('<img src="%s?img=manualplus" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1148
            $output .= sprintf(
1149
                        '<a href="http://pear.php.net/manual/en/" class="green" target="_new">%s pear.php.net Package Manual </a>',
1150
                        $image);
1151
        }
1152
        $tpl->setVariable('More_Data', $output);
1153
 
1154
        $tpl->show();
1155
        return true;
1156
    }
1157
 
1158
    /**
1159
     * Output given data in a horizontal generic table:
1160
     * table headers in the top row.
1161
     * Possibly prepend caption
1162
     *
1163
     * @var string $caption possible caption for table
1164
     * @var array $data array of data items
1165
     * @return true optimist etc
1166
     */
1167
    function _outputGenericTableHorizontal($caption, $data) {
1168
        $tpl = $this->_initTemplate('generic_table_horizontal.tpl.html');
1169
 
1170
        if (!is_null($caption) && $caption != '') {
1171
            $tpl->setVariable('Caption', $caption);
1172
        }
1173
 
1174
        if (!is_array($data)) {
1175
            $tpl->setCurrentBlock('Data_row');
1176
            $tpl->setVariable('Text', nl2br($data));
1177
            $tpl->parseCurrentBlock();
1178
        } else {
1179
            foreach ($data as $row) {
1180
                foreach ($row as $col) {
1181
                    $tpl->setCurrentBlock('Row_item');
1182
                    $tpl->setVariable('Text', nl2br($col));
1183
                    $tpl->parseCurrentBlock();
1184
                }
1185
                $tpl->setCurrentBlock('Data_row');
1186
                $tpl->parseCurrentBlock();
1187
            }
1188
        }
1189
 
1190
        $tpl->show();
1191
        return true;
1192
    }
1193
 
1194
    /**
1195
     * Output given data in a vertical generic table:
1196
     * table headers in the left column.
1197
     * Possibly prepend caption
1198
     *
1199
     * @var string $caption possible caption for table
1200
     * @var array $data array of data items
1201
     * @return true optimist etc
1202
     */
1203
    function _outputGenericTableVertical($caption, $data) {
1204
        $tpl = $this->_initTemplate('generic_table_vertical.tpl.html');
1205
 
1206
        if (!is_null($caption) && $caption != '') {
1207
            $tpl->setVariable("Caption", $caption);
1208
        }
1209
 
1210
        if (!is_array($data)) {
1211
            $tpl->setCurrentBlock('Data_row');
1212
            $tpl->setVariable('Title', '&nbsp;');
1213
            $tpl->setVariable('Text', nl2br($data));
1214
            $tpl->parseCurrentBlock();
1215
        } else {
1216
            foreach($data as $row) {
1217
                $tpl->setCurrentBlock('Data_row');
1218
                $tpl->setVariable('Title', $row[0]);
1219
                $tpl->setVariable('Text', nl2br($row[1]));
1220
                $tpl->parseCurrentBlock();
1221
            }
1222
        }
1223
 
1224
        $tpl->show();
1225
        return true;
1226
    }
1227
 
1228
    /**
1229
     * Output details of one channel
1230
     *
1231
     * @param array $data array containing all information about the channel
1232
     *
1233
     * @return boolean true (yep. i am an optimist)
1234
     */
1235
    function _outputChannelInfo($data)
1236
    {
1237
        $data['main']['data'] = $this->htmlentities_recursive($data['main']['data']);
1238
        $channel = $data['main']['data']['server'][1];
1239
        $output = '';
1240
 
1241
        if ($channel != '__uri') {
1242
            // add 'More' options
1243
            $image = sprintf('<img src="%s?img=package" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1244
            $output .= sprintf(
1245
                    '<a href="%s?command=list-packages&chan=%s" class="green">%s List all packagenames of this channel</a>',
1246
                    $_SERVER["PHP_SELF"],
1247
                    $channel,
1248
                    $image);
1249
            $output .= '<br />';
1250
            $image = sprintf('<img src="%s?img=category" border="0" alt="manual">', $_SERVER["PHP_SELF"]);
1251
            $output .= sprintf(
1252
                    '<a href="%s?command=list-categories&chan=%s" class="green">%s List all categories of this channel</a>',
1253
                    $_SERVER["PHP_SELF"],
1254
                    $channel,
1255
                    $image);
1256
            $output .= '<br />';
1257
            $output .= sprintf(
1258
                    '<a href="%s?command=list-categories&chan=%s&opt=packages" class="green">%s List all categories, with packagenames, of this channel</a>',
1259
                    $_SERVER["PHP_SELF"],
1260
                    $channel,
1261
                    $image);
1262
            $data['main']['data']['more'] = array('More', $output);
1263
        }
1264
 
1265
        return $this->_outputGenericTableVertical($data['main']['caption'], $data['main']['data']);
1266
    }
1267
 
1268
    /**
1269
     * Output all kinds of data depending on the command which called this method
1270
     *
1271
     * @param mixed  $data    datastructure containing the information to display
1272
     * @param string $command (optional) command from which this method was called
1273
     *
1274
     * @access public
1275
     *
1276
     * @return mixed highly depends on the command
1277
     */
1278
    function outputData($data, $command = '_default')
1279
    {
1280
        switch ($command) {
1281
            case 'config-show':
1282
                $prompt  = array();
1283
                $default = array();
1284
                foreach($data['data'] as $group) {
1285
                    foreach($group as $row) {
1286
                        $prompt[$row[1]]  = $row[0];
1287
                        $default[$row[1]] = $row[2];
1288
                    }
1289
                }
1290
                $title = 'Configuration :: '.$GLOBALS['pear_user_config'];
1291
                $GLOBALS['_PEAR_Frontend_Web_Config'] =
1292
                    $this->userDialog($command, $prompt, array(), $default, $title, 'config');
1293
                return true;
1294
            case 'list-files':
1295
                return $this->_outputListFiles($data);
1296
            case 'list-docs':
1297
                return $this->_outputListDocs($data);
1298
            case 'doc-show':
1299
                return $this->_outputDocShow($data);
1300
            case 'list-all':
1301
                return $this->_outputListAll($data);
1302
            case 'list-packages':
1303
                return $this->_outputListPackages($data);
1304
            case 'list-categories':
1305
                return $this->_outputListCategories($data);
1306
            case 'list-category':
1307
                return $this->_outputListCategory($data);
1308
            case 'list-upgrades':
1309
                return $this->_outputListUpgrades($data);
1310
            case 'list':
1311
                return $this->_outputList($data);
1312
            case 'list-channels':
1313
                return $this->_outputListChannels($data);
1314
            case 'search':
1315
                return $this->_outputListAll($data, false);
1316
            case 'remote-info':
1317
                return $this->_outputPackageRemoteInfo($data);
1318
            case 'package-info': // = 'info' command
1319
                return $this->_outputPackageInfo($data);
1320
            case 'channel-info':
1321
                return $this->_outputChannelInfo($data);
1322
            case 'login':
1323
                if ($_SERVER["REQUEST_METHOD"] != "POST")
1324
                    $this->_data[$command] = $data;
1325
                return true;
1326
            case 'logout':
1327
                $this->displayError($data, 'Logout', 'logout');
1328
                break;
1329
            case 'install':
1330
            case 'upgrade':
1331
            case 'upgrade-all':
1332
            case 'uninstall':
1333
            case 'channel-delete':
1334
            case 'package':
1335
            case 'channel-discover':
1336
            case 'update-channels':
1337
            case 'channel-update':
1338
                if (is_array($data)) {
1339
                    print($data['data'].'<br />');
1340
                } else {
1341
                    print($data.'<br />');
1342
                }
1343
                break;
1344
            default:
1345
                if ($this->_installScript) {
1346
                    $this->_savedOutput[] = $_SESSION['_PEAR_Frontend_Web_SavedOutput'][] = $data;
1347
                    break;
1348
                }
1349
                if (!is_array($data)) {
1350
                    // WARNING: channel "pear.php.net" has updated its protocols, use "channel-update pear.php.net" to update: auto-URL
1351
                    if (preg_match('/use "channel-update ([\S]+)" to update$/', $data, $matches)) {
1352
                        $channel = $matches[1];
1353
                        $url = sprintf('<a href="%s?command=channel-update&chan=%s" class="green">channel-update %s</a>',
1354
                                $_SERVER['PHP_SELF'],
1355
                                $channel,
1356
                                $channel);
1357
                        $data = preg_replace('/channel-update '.$channel.'/',
1358
                                                $url,
1359
                                                $data);
1360
                    }
1361
 
1362
                    // pearified/Role_Web has post-install scripts: bold
1363
                    if (strpos($data, 'has post-install scripts:') !== false) {
1364
                        $data = '<br /><i>'.$data.'</i>';
1365
                    }
1366
                    // Use "pear run-scripts pearified/Role_Web" to run
1367
                    if (preg_match('/^Use "pear run-scripts ([\S]+)"$/', $data, $matches)) {
1368
                        $pkg = $matches[1];
1369
                        $url = sprintf('<a href="%s?command=run-scripts&pkg=%s" class="green">pear run-scripts %s</a>',
1370
                                $_SERVER['PHP_SELF'],
1371
                                $pkg,
1372
                                $pkg);
1373
                        $pkg = str_replace('/', '\/', $pkg);
1374
                        $data = preg_replace('/pear run-scripts '.$pkg.'/',
1375
                                                $url,
1376
                                                $data);
1377
                        $data = '<b>Attention !</b> '.$data.' !';
1378
                    }
1379
                    if (strpos($data, 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES') !== false) {
1380
                        break;
1381
                    }
1382
 
1383
                    // TODO: div magic, give it a color and a box etc.
1384
                    print('<div>'.$data.'<div>');
1385
                }
1386
        }
1387
 
1388
        return true;
1389
    }
1390
 
1391
    /**
1392
     * Output a Table Of Channels:
1393
     * Table of contents like thing for all channels
1394
     * (using <a name= stuff
1395
     */
1396
    function outputTableOfChannels()
1397
    {
1398
        $tpl = $this->_initTemplate('tableofchannels.tpl.html');
1399
        $tpl->setVariable('Caption', 'All available channels:');
1400
 
1401
        $reg = $this->config->getRegistry();
1402
        $channels = $reg->getChannels();
1403
        foreach ($channels as $channel) {
1404
            if ($channel->getName() != '__uri') {
1405
                $tpl->setCurrentBlock('Data_row');
1406
                $tpl->setVariable('Channel', $channel->getName());
1407
                $tpl->parseCurrentBlock();
1408
            }
1409
        }
1410
 
1411
        $tpl->show();
1412
    }
1413
 
1414
    /**
1415
     * Output the 'upgrade-all' page
1416
     */
1417
    function outputUpgradeAll()
1418
    {
1419
        $tpl = $this->_initTemplate('upgrade_all.tpl.html');
1420
        $tpl->setVariable('UpgradeAllURL', $_SERVER['PHP_SELF']);
1421
        $tpl->show();
1422
    }
1423
 
1424
    /**
1425
     * Output the 'search' page
1426
     */
1427
    function outputSearch()
1428
    {
1429
        $reg = $this->config->getRegistry();
1430
        $channels = $reg->getChannels();
1431
        $channel_select = array('all' => 'All channels');
1432
        foreach ($channels as $channel) {
1433
            if ($channel->getName() != '__uri') {
1434
                $channel_select[$channel->getName()] = $channel->getName();
1435
            }
1436
        }
1437
 
1438
        // search-types to display
1439
        $arr = array(
1440
              'name' => array('title' => 'Search package by name (fast)',
1441
                              'descr' => 'Package name'),
1442
              'description' => array('title' => 'Search package by name and description (slow)',
1443
                                     'descr' => 'Search:'),
1444
             );
1445
 
1446
        foreach($arr as $type => $values) {
1447
            $tpl = $this->_initTemplate('search.tpl.html');
1448
            $tpl->setCurrentBlock('Search');
1449
            foreach($channel_select as $key => $value) {
1450
                $tpl->setCurrentBlock('Search_channel');
1451
                $tpl->setVariable('Key', $key);
1452
                $tpl->setVariable('Value', $value);
1453
                $tpl->parseCurrentBlock();
1454
            }
1455
            $tpl->setVariable('InstallerURL', $_SERVER['PHP_SELF']);
1456
            $tpl->setVariable('Search_type', $type);
1457
            $tpl->setVariable('Title', $values['title']);
1458
            $tpl->setVariable('Description', $values['descr']);
1459
            $tpl->parseCurrentBlock();
1460
            $tpl->show();
1461
        }
1462
    }
1463
 
1464
    /**
1465
     * Start session: starts saving output temporary
1466
     */
1467
    function startSession()
1468
    {
1469
        if ($this->_installScript) {
1470
            if (!isset($_SESSION['_PEAR_Frontend_Web_SavedOutput'])) {
1471
                $_SESSION['_PEAR_Frontend_Web_SavedOutput'] = array();
1472
            }
1473
            $this->_savedOutput = $_SESSION['_PEAR_Frontend_Web_SavedOutput'];
1474
        } else {
1475
            $this->_savedOutput = array();
1476
        }
1477
    }
1478
 
1479
    /**
1480
     * End session: output all saved output
1481
     */
1482
    function finishOutput($command, $redirectLink = false)
1483
    {
1484
        unset($_SESSION['_PEAR_Frontend_Web_SavedOutput']);
1485
        $tpl = $this->_initTemplate('info.tpl.html');
1486
        foreach($this->_savedOutput as $row) {
1487
            $tpl->setCurrentBlock('Infoloop');
1488
            $tpl->setVariable("Info", $row);
1489
            $tpl->parseCurrentBlock();
1490
        }
1491
        if ($redirectLink) {
1492
            $tpl->setCurrentBlock('Infoloop');
1493
            $tpl->setVariable("Info", '<a href="' . $redirectLink['link'] . '" class="green">' .
1494
                $redirectLink['text'] . '</a>');
1495
            $tpl->parseCurrentBlock();
1496
        }
1497
        $tpl->show();
1498
    }
1499
 
1500
    /**
1501
     * Run postinstall scripts
1502
     *
1503
     * @param array An array of PEAR_Task_Postinstallscript objects (or related scripts)
1504
     * @param PEAR_PackageFile_v2
1505
     */
1506
    function runPostinstallScripts(&$scripts, $pkg)
1507
    {
1508
        if (!isset($_SESSION['_PEAR_Frontend_Web_Scripts'])) {
1509
            $saves = array();
1510
            foreach ($scripts as $i => $task) {
1511
                $saves[$i] = (array) $task->_obj;
1512
            }
1513
            $_SESSION['_PEAR_Frontend_Web_Scripts'] = $saves;
1514
            $nonsession = true;
1515
        } else {
1516
            $nonsession = false;
1517
        }
1518
        foreach ($scripts as $i => $task) {
1519
            if (!isset($_SESSION['_PEAR_Frontend_Web_ScriptIndex'])) {
1520
                $_SESSION['_PEAR_Frontend_Web_ScriptIndex'] = $i;
1521
            }
1522
            if ($i != $_SESSION['_PEAR_Frontend_Web_ScriptIndex']) {
1523
                continue;
1524
            }
1525
            if (!$nonsession) {
1526
                // restore values from previous sessions to the install script
1527
                foreach ($_SESSION['_PEAR_Frontend_Web_Scripts'][$i] as $name => $val) {
1528
                    if ($name{0} == '_') {
1529
                        // only public variables will be restored
1530
                        continue;
1531
                    }
1532
                    $scripts[$i]->_obj->$name = $val;
1533
                }
1534
            }
1535
            $this->_installScript = true;
1536
            $this->startSession();
1537
            $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj, $pkg);
1538
            $saves = $scripts;
1539
            foreach ($saves as $i => $task) {
1540
                $saves[$i] = (array) $task->_obj;
1541
            }
1542
            $_SESSION['_PEAR_Frontend_Web_Scripts'] = $saves;
1543
            unset($_SESSION['_PEAR_Frontend_Web_ScriptIndex']);
1544
        }
1545
        $this->_installScript = false;
1546
        unset($_SESSION['_PEAR_Frontend_Web_Scripts']);
1547
        $pkg_full = $pkg->getChannel().'/'.$pkg->getPackage();
1548
        $this->finishOutput($pkg_full . ' Install Script',
1549
            array('link' => $_SERVER['PHP_SELF'] .
1550
            '?command=info&pkg='.$pkg_full,
1551
                'text' => 'Click for ' .$pkg_full. ' Information'));
1552
    }
1553
 
1554
    /**
1555
     * Instruct the runInstallScript method to skip a paramgroup that matches the
1556
     * id value passed in.
1557
     *
1558
     * This method is useful for dynamically configuring which sections of a post-install script
1559
     * will be run based on the user's setup, which is very useful for making flexible
1560
     * post-install scripts without losing the cross-Frontend ability to retrieve user input
1561
     * @param string
1562
     */
1563
    function skipParamgroup($id)
1564
    {
1565
        $_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'][$sectionName] = true;
1566
    }
1567
 
1568
    /**
1569
     * @param array $xml contents of postinstallscript tag
1570
     *  example: Array (
1571
                [paramgroup] => Array (
1572
                    [id] => webSetup
1573
                    [param] => Array (
1574
                        [name] => webdirpath
1575
                        [prompt] => Where should... ?
1576
                        [default] => '/var/www/htdocs/webpear
1577
                        [type] => string
1578
                        )
1579
                    )
1580
                )
1581
     * @param object $script post-installation script
1582
     * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
1583
     * @param string $contents contents of the install script
1584
     */
1585
    function runInstallScript($xml, &$script, &$pkg)
1586
    {
1587
        if (!isset($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'])) {
1588
            $_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'] = array();
1589
            $_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'] = array();
1590
        }
1591
        if (isset($_SESSION['_PEAR_Frontend_Web_ScriptObj'])) {
1592
            foreach ($_SESSION['_PEAR_Frontend_Web_ScriptObj'] as $name => $val) {
1593
                if ($name{0} == '_') {
1594
                    // only public variables will be restored
1595
                    continue;
1596
                }
1597
                $script->$name = $val;
1598
            }
1599
        } else {
1600
            $_SESSION['_PEAR_Frontend_Web_ScriptObj'] = (array) $script;
1601
        }
1602
        if (!is_array($xml) || !isset($xml['paramgroup'])) {
1603
            $script->run(array(), '_default');
1604
        } else {
1605
            if (!isset($xml['paramgroup'][0])) {
1606
                $xml['paramgroup'] = array($xml['paramgroup']);
1607
            }
1608
            foreach ($xml['paramgroup'] as $i => $group) {
1609
                if (isset($_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'][$group['id']])) {
1610
                    continue;
1611
                }
1612
                if (isset($_SESSION['_PEAR_Frontend_Web_ScriptSection'])) {
1613
                    if ($i < $_SESSION['_PEAR_Frontend_Web_ScriptSection']) {
1614
                        $lastgroup = $group;
1615
                        continue;
1616
                    }
1617
                }
1618
                if (isset($_SESSION['_PEAR_Frontend_Web_answers'])) {
1619
                    $answers = $_SESSION['_PEAR_Frontend_Web_answers'];
1620
                }
1621
                if (isset($group['name'])) {
1622
                    if (isset($answers)) {
1623
                        if (isset($answers[$group['name']])) {
1624
                            switch ($group['conditiontype']) {
1625
                                case '=' :
1626
                                    if ($answers[$group['name']] != $group['value']) {
1627
                                        continue 2;
1628
                                    }
1629
                                break;
1630
                                case '!=' :
1631
                                    if ($answers[$group['name']] == $group['value']) {
1632
                                        continue 2;
1633
                                    }
1634
                                break;
1635
                                case 'preg_match' :
1636
                                    if (!@preg_match('/' . $group['value'] . '/',
1637
                                          $answers[$group['name']])) {
1638
                                        continue 2;
1639
                                    }
1640
                                break;
1641
                                default :
1642
                                    $this->_clearScriptSession();
1643
                                return;
1644
                            }
1645
                        }
1646
                    } else {
1647
                        $this->_clearScriptSession();
1648
                        return;
1649
                    }
1650
                }
1651
                if (!isset($group['param'][0])) {
1652
                    $group['param'] = array($group['param']);
1653
                }
1654
                $_SESSION['_PEAR_Frontend_Web_ScriptSection'] = $i;
1655
                if (!isset($answers)) {
1656
                    $answers = array();
1657
                }
1658
                if (isset($group['param'])) {
1659
                    if (method_exists($script, 'postProcessPrompts')) {
1660
                        $prompts = $script->postProcessPrompts($group['param'], $group['name']);
1661
                        if (!is_array($prompts) || count($prompts) != count($group['param'])) {
1662
                            $this->outputData('postinstall', 'Error: post-install script did not ' .
1663
                                'return proper post-processed prompts');
1664
                            $prompts = $group['param'];
1665
                        } else {
1666
                            foreach ($prompts as $i => $var) {
1667
                                if (!is_array($var) || !isset($var['prompt']) ||
1668
                                      !isset($var['name']) ||
1669
                                      ($var['name'] != $group['param'][$i]['name']) ||
1670
                                      ($var['type'] != $group['param'][$i]['type'])) {
1671
                                    $this->outputData('postinstall', 'Error: post-install script ' .
1672
                                        'modified the variables or prompts, severe security risk. ' .
1673
                                        'Will instead use the defaults from the package.xml');
1674
                                    $prompts = $group['param'];
1675
                                }
1676
                            }
1677
                        }
1678
                        $answers = array_merge($answers,
1679
                            $this->confirmDialog($prompts,
1680
                                $pkg->getChannel().'/'.$pkg->getPackage()));
1681
                    } else {
1682
                        $answers = array_merge($answers,
1683
                            $this->confirmDialog($group['param'],
1684
                                $pkg->getChannel().'/'.$pkg->getPackage()));
1685
                    }
1686
                }
1687
                if ($answers) {
1688
                    array_unshift($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'],
1689
                        $group['id']);
1690
                    if (!$script->run($answers, $group['id'])) {
1691
                        $script->run($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'],
1692
                            '_undoOnError');
1693
                        $this->_clearScriptSession();
1694
                        return;
1695
                    }
1696
                } else {
1697
                    $script->run(array(), '_undoOnError');
1698
                    $this->_clearScriptSession();
1699
                    return;
1700
                }
1701
                $lastgroup = $group;
1702
                foreach ($group['param'] as $param) {
1703
                    // rename the current params to save for future tests
1704
                    $answers[$group['id'] . '::' . $param['name']] = $answers[$param['name']];
1705
                    unset($answers[$param['name']]);
1706
                }
1707
                // save the script's variables and user answers for the next round
1708
                $_SESSION['_PEAR_Frontend_Web_ScriptObj'] = (array) $script;
1709
                $_SESSION['_PEAR_Frontend_Web_answers'] = $answers;
1710
                $_SERVER['REQUEST_METHOD'] = '';
1711
            }
1712
        }
1713
        $this->_clearScriptSession();
1714
    }
1715
 
1716
    function _clearScriptSession()
1717
    {
1718
        unset($_SESSION['_PEAR_Frontend_Web_ScriptObj']);
1719
        unset($_SESSION['_PEAR_Frontend_Web_answers']);
1720
        unset($_SESSION['_PEAR_Frontend_Web_ScriptSection']);
1721
        unset($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases']);
1722
        unset($_SESSION['_PEAR_Frontend_Web_ScriptSkipSections']);
1723
    }
1724
 
1725
    /**
1726
     * Ask for user input, confirm the answers and continue until the user is satisfied
1727
     *
1728
     * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
1729
     *              'text to display', 'type' => 'string'[, default => 'default value'])
1730
     * @param string Package Name
1731
     * @return array|false
1732
     */
1733
    function confirmDialog($params, $pkg)
1734
    {
1735
        $answers = array();
1736
        $prompts = $types = array();
1737
        foreach ($params as $param) {
1738
            $prompts[$param['name']] = $param['prompt'];
1739
            $types[$param['name']] = $param['type'];
1740
            if (isset($param['default'])) {
1741
                $answers[$param['name']] = $param['default'];
1742
            } else {
1743
                $answers[$param['name']] = '';
1744
            }
1745
        }
1746
        $attempt = 0;
1747
        do {
1748
            if ($attempt) {
1749
                $_SERVER['REQUEST_METHOD'] = '';
1750
            }
1751
            $title = !$attempt ? $pkg . ' Install Script Input' : 'Please fill in all values';
1752
            $answers = $this->userDialog('run-scripts', $prompts, $types, $answers, $title, '',
1753
                array('pkg' => $pkg));
1754
            if ($answers === false) {
1755
                return false;
1756
            }
1757
            $attempt++;
1758
        } while (count(array_filter($answers)) != count($prompts));
1759
        $_SERVER['REQUEST_METHOD'] = 'POST';
1760
        return $answers;
1761
    }
1762
 
1763
    /**
1764
     * Useless function that needs to exists for Frontend::setFrontendObject()
1765
     * Reported in bug #10656
1766
     */
1767
    function userConfirm($prompt, $default = 'yes')
1768
    {
1769
        trigger_error("PEAR_Frontend_Web::userConfirm not used", E_USER_ERROR);
1770
    }
1771
 
1772
    /**
1773
     * Display a formular and return the given input (yes. needs to requests)
1774
     *
1775
     * @param string $command  command from which this method was called
1776
     * @param array  $prompts  associative array. keys are the inputfieldnames
1777
     *                         and values are the description
1778
     * @param array  $types    (optional) array of inputfieldtypes (text, password,
1779
     *                         etc.) keys have to be the same like in $prompts
1780
     * @param array  $defaults (optional) array of defaultvalues. again keys have
1781
     *                         to be the same like in $prompts
1782
     * @param string $title    (optional) title of the page
1783
     * @param string $icon     (optional) iconhandle for this page
1784
     * @param array  $extra    (optional) extra parameters to put in the form action
1785
     *
1786
     * @access public
1787
     *
1788
     * @return array input sended by the user
1789
     */
1790
    function userDialog($command, $prompts, $types = array(), $defaults = array(), $title = '',
1791
                        $icon = '', $extra = array())
1792
    {
1793
        // If this is an POST Request, we can return the userinput
1794
        if (isset($_GET["command"]) && $_GET["command"]==$command
1795
            && $_SERVER["REQUEST_METHOD"] == "POST") {
1796
            if (isset($_POST['cancel'])) {
1797
                return false;
1798
            }
1799
            $result = array();
1800
            foreach($prompts as $key => $prompt) {
1801
                $result[$key] = $_POST[$key];
1802
            }
1803
            return $result;
1804
        }
1805
 
1806
        // If this is an Answer GET Request , we can return the userinput
1807
        if (isset($_GET["command"]) && $_GET["command"]==$command
1808
            && isset($_GET["userDialogResult"]) && $_GET["userDialogResult"]=='get') {
1809
            $result = array();
1810
            foreach($prompts as $key => $prompt) {
1811
                $result[$key] = $_GET[$key];
1812
            }
1813
            return $result;
1814
        }
1815
 
1816
        // Assign title and icon to some commands
1817
        if ($command == 'login') {
1818
            $title = 'Login';
1819
        }
1820
 
1821
        $tpl = $this->_initTemplate('userDialog.tpl.html');
1822
        $tpl->setVariable("Command", $command);
1823
        $extrap = '';
1824
        if (count($extra)) {
1825
            $extrap = '&';
1826
            foreach ($extra as $name => $value) {
1827
                $extrap .= urlencode($name) . '=' . urlencode($value);
1828
            }
1829
        }
1830
        $tpl->setVariable("extra", $extrap);
1831
        if ($title != '') {
1832
            $tpl->setVariable('Caption', $title);
1833
        } else {
1834
            $tpl->setVariable('Caption', ucfirst($command));
1835
        }
1836
 
1837
        if (is_array($prompts)) {
1838
            $maxlen = 0;
1839
            foreach($prompts as $key => $prompt) {
1840
                if (strlen($prompt) > $maxlen) {
1841
                    $maxlen = strlen($prompt);
1842
                }
1843
            }
1844
 
1845
            foreach($prompts as $key => $prompt) {
1846
                $tpl->setCurrentBlock("InputField");
1847
                $type    = (isset($types[$key])    ? $types[$key]    : 'text');
1848
                $default = (isset($defaults[$key]) ? $defaults[$key] : '');
1849
                $tpl->setVariable("prompt", $prompt);
1850
                $tpl->setVariable("name", $key);
1851
                $tpl->setVariable("default", $default);
1852
                $tpl->setVariable("type", $type);
1853
                if ($maxlen > 25) {
1854
                    $tpl->setVariable("width", 'width="275"');
1855
                }
1856
                $tpl->parseCurrentBlock();
1857
            }
1858
        }
1859
        if ($command == 'run-scripts') {
1860
            $tpl->setVariable("cancel", '<input type="submit" value="Cancel" name="cancel">');
1861
        }
1862
        $tpl->show();
1863
        exit;
1864
    }
1865
 
1866
    /**
1867
     * Write message to log
1868
     *
1869
     * @param string $text message which has to written to log
1870
     *
1871
     * @access public
1872
     *
1873
     * @return boolean true
1874
     */
1875
    function log($text)
1876
    {
1877
        if ($text == '.') {
1878
            print($text);
1879
        } else {
1880
            // filter some log output:
1881
            // color some things, drop some others
1882
            $styled = false;
1883
 
1884
            // color:error {Failed to download pear/MDB2_Schema within preferred state "stable", latest release is version 0.7.2, stability "beta", use "channel://pear.php.net/MDB2_Schema-0.7.2" to install}
1885
            // make hyperlink the 'channel://...' part
1886
            $pattern = 'Failed to download';
1887
            if (substr($text, 0, strlen($pattern)) == $pattern) {
1888
                // hyperlink
1889
                if (preg_match('/use "channel:\/\/([\S]+)" to install/', $text, $matches)) {
1890
                    $pkg = $matches[1];
1891
                    $url = sprintf('<a href="%s?command=upgrade&pkg=%s" onClick="return installPkg(\'%s\');" class="green">channel://%s</a>',
1892
                                $_SERVER['PHP_SELF'],
1893
                                urlencode($pkg),
1894
                                $pkg,
1895
                                $pkg);
1896
                    $text = preg_replace('/channel:\/\/'.addcslashes($pkg, '/').'/',
1897
                                         $url,
1898
                                         $text);
1899
                }
1900
                // color
1901
                $text = '<div id="error">'.$text.'</div>';
1902
                $styled = true;
1903
            }
1904
 
1905
            // color:warning {chiara/Chiara_Bugs requires package "chiara/Chiara_PEAR_Server" (version >= 0.18.4) || chiara/Chiara_Bugs requires package "channel://savant.pearified.com/Savant3" (version >= 3.0.0)}
1906
            // make hyperlink the 'ch/pkg || channel://ch/pkg' part
1907
            $pattern = ' requires package "';
1908
            if (!$styled && strpos($text, $pattern) !== false) {
1909
                // hyperlink
1910
                if (preg_match('/ package "([\S]+)" \(version /', $text, $matches)) {
1911
                    $pkg = $matches[1];
1912
                    if (substr($pkg, 0, strlen('channel://')) == 'channel://') {
1913
                        $pkg = substr($pkg, strlen('channel://'));
1914
                    }
1915
                    $url = sprintf('<a href="%s?command=info&pkg=%s" class="green">%s</a>',
1916
                                $_SERVER['PHP_SELF'],
1917
                                urlencode($pkg),
1918
                                $matches[1]);
1919
                    $text = preg_replace('/'.addcslashes($matches[1], '/').'/',
1920
                                         $url,
1921
                                         $text);
1922
                }
1923
                // color
1924
                $text = '<div id="warning">'.$text.'</div>';
1925
                $styled = true;
1926
            }
1927
 
1928
            // color:warning {Could not download from "http://pear.php.net/get/HTML_QuickForm-3.2.9.tgz", cannot download "pear/html_quickform" (could not open /home/tias/WASP/pear/cvs//temp/download/HTML_QuickForm-3.2.9.tgz for writing)}
1929
            $pattern = 'Could not download from';
1930
            if (substr($text, 0, strlen($pattern)) == $pattern) {
1931
                // color
1932
                $text = '<div id="warning">'.$text.'</div>';
1933
                $styled = true;
1934
            }
1935
 
1936
            // color:error {Error: cannot download "pear/HTML_QuickForm"}
1937
            $pattern = 'Error:';
1938
            if (substr($text, 0, strlen($pattern)) == $pattern) {
1939
                // color
1940
                $text = '<div id="error">'.$text.'</div>';
1941
                $styled = true;
1942
            }
1943
 
1944
            // and output...
1945
            if (!$styled) {
1946
                $text = '<div id="log">'.$text.'</div>';
1947
            }
1948
            print($text);
1949
        }
1950
 
1951
        return true;
1952
    }
1953
 
1954
    /**
1955
     * Totaly deprecated function
1956
     * Needed to install pearified's role_web : /
1957
     * Don't use this !
1958
     */
1959
    function bold($text)
1960
    {
1961
        print('<b>'.$text.'</b><br />');
1962
    }
1963
 
1964
    /**
1965
     * Sends the required file along with Headers and exits the script
1966
     *
1967
     * @param string $handle handle of the requested file
1968
     * @param string $group  group of the requested file
1969
     *
1970
     * @access public
1971
     *
1972
     * @return null nothing, because script exits
1973
     */
1974
    function outputFrontendFile($handle, $group)
1975
    {
1976
        $handles = array(
1977
            "css" => array(
1978
                "style" => "style.css",
1979
                ),
1980
            "js" => array(
1981
                "package" => "package.js",
1982
                ),
1983
            "image" => array(
1984
                "logout" => array(
1985
                    "type" => "gif",
1986
                    "file" => "logout.gif",
1987
                    ),
1988
                "login" => array(
1989
                    "type" => "gif",
1990
                    "file" => "login.gif",
1991
                    ),
1992
                "config" => array(
1993
                    "type" => "gif",
1994
                    "file" => "config.gif",
1995
                    ),
1996
                "pkglist" => array(
1997
                    "type" => "png",
1998
                    "file" => "pkglist.png",
1999
                    ),
2000
                "pkgsearch" => array(
2001
                    "type" => "png",
2002
                    "file" => "pkgsearch.png",
2003
                    ),
2004
                "package" => array(
2005
                    "type" => "jpeg",
2006
                    "file" => "package.jpg",
2007
                    ),
2008
                "category" => array(
2009
                    "type" => "jpeg",
2010
                    "file" => "category.jpg",
2011
                    ),
2012
                "install" => array(
2013
                    "type" => "gif",
2014
                    "file" => "install.gif",
2015
                    ),
2016
                "install_wait" => array(
2017
                    "type" => "gif",
2018
                    "file" => "install_wait.gif",
2019
                    ),
2020
                "install_ok" => array(
2021
                    "type" => "gif",
2022
                    "file" => "install_ok.gif",
2023
                    ),
2024
                "install_fail" => array(
2025
                    "type" => "gif",
2026
                    "file" => "install_fail.gif",
2027
                    ),
2028
                "uninstall" => array(
2029
                    "type" => "gif",
2030
                    "file" => "trash.gif",
2031
                    ),
2032
                "info" => array(
2033
                    "type" => "gif",
2034
                    "file" => "info.gif",
2035
                    ),
2036
                "infoplus" => array(
2037
                    "type" => "gif",
2038
                    "file" => "infoplus.gif",
2039
                    ),
2040
                "pear" => array(
2041
                    "type" => "gif",
2042
                    "file" => "pearsmall.gif",
2043
                    ),
2044
                "error" => array(
2045
                    "type" => "gif",
2046
                    "file" => "error.gif",
2047
                    ),
2048
                "manual" => array(
2049
                    "type" => "gif",
2050
                    "file" => "manual.gif",
2051
                    ),
2052
                "manualplus" => array(
2053
                    "type" => "gif",
2054
                    "file" => "manualplus.gif",
2055
                    ),
2056
                "download" => array(
2057
                    "type" => "gif",
2058
                    "file" => "download.gif",
2059
                    ),
2060
                ),
2061
            );
2062
 
2063
        $file = $handles[$group][$handle];
2064
        switch ($group) {
2065
            case 'css':
2066
                header("Content-Type: text/css");
2067
                readfile($this->config->get('data_dir').'/PEAR_Frontend_Web/data/'.$file);
2068
                exit;
2069
            case 'image':
2070
                $filename = $this->config->get('data_dir').'/PEAR_Frontend_Web/data/images/'.$file['file'];
2071
                header("Content-Type: image/".$file['type']);
2072
                header("Expires: ".gmdate("D, d M Y H:i:s \G\M\T", time() + 60*60*24*100));
2073
                header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", filemtime($filename)));
2074
                header("Cache-Control: public");
2075
                header("Pragma: ");
2076
                readfile($filename);
2077
                exit;
2078
            case 'js':
2079
                header("Content-Type: text/javascript");
2080
                readfile($this->config->get('data_dir').'/PEAR_Frontend_Web/data/'.$file);
2081
                exit;
2082
        }
2083
    }
2084
 
2085
    /*
2086
     * From DB::Pager. Removing Pager dependency.
2087
     * @private
2088
     */
2089
    function __getData($from, $limit, $numrows, $maxpages = false)
2090
    {
2091
        if (empty($numrows) || ($numrows < 0)) {
2092
            return null;
2093
        }
2094
        $from = (empty($from)) ? 0 : $from;
2095
 
2096
        if ($limit <= 0) {
2097
            return false;
2098
        }
2099
 
2100
        // Total number of pages
2101
        $pages = ceil($numrows/$limit);
2102
        $data['numpages'] = $pages;
2103
 
2104
        // first & last page
2105
        $data['firstpage'] = 1;
2106
        $data['lastpage']  = $pages;
2107
 
2108
        // Build pages array
2109
        $data['pages'] = array();
2110
        for ($i=1; $i <= $pages; $i++) {
2111
            $offset = $limit * ($i-1);
2112
            $data['pages'][$i] = $offset;
2113
            // $from must point to one page
2114
            if ($from == $offset) {
2115
                // The current page we are
2116
                $data['current'] = $i;
2117
            }
2118
        }
2119
        if (!isset($data['current'])) {
2120
            return PEAR::raiseError (null, 'wrong "from" param', null,
2121
                                     null, null, 'DB_Error', true);
2122
        }
2123
              // Limit number of pages (Goole algorithm)
2124
        if ($maxpages) {
2125
            $radio = floor($maxpages/2);
2126
            $minpage = $data['current'] - $radio;
2127
            if ($minpage < 1) {
2128
                $minpage = 1;
2129
            }
2130
            $maxpage = $data['current'] + $radio - 1;
2131
            if ($maxpage > $data['numpages']) {
2132
                $maxpage = $data['numpages'];
2133
            }
2134
            foreach (range($minpage, $maxpage) as $page) {
2135
                $tmp[$page] = $data['pages'][$page];
2136
            }
2137
            $data['pages'] = $tmp;
2138
            $data['maxpages'] = $maxpages;
2139
        } else {
2140
            $data['maxpages'] = null;
2141
        }
2142
 
2143
        // Prev link
2144
        $prev = $from - $limit;
2145
        $data['prev'] = ($prev >= 0) ? $prev : null;
2146
 
2147
        // Next link
2148
        $next = $from + $limit;
2149
        $data['next'] = ($next < $numrows) ? $next : null;
2150
 
2151
        // Results remaining in next page & Last row to fetch
2152
        if ($data['current'] == $pages) {
2153
            $data['remain'] = 0;
2154
            $data['to'] = $numrows;
2155
        } else {
2156
            if ($data['current'] == ($pages - 1)) {
2157
                $data['remain'] = $numrows - ($limit*($pages-1));
2158
            } else {
2159
                $data['remain'] = $limit;
2160
            }
2161
            $data['to'] = $data['current'] * $limit;
2162
        }
2163
        $data['numrows'] = $numrows;
2164
        $data['from']    = $from + 1;
2165
        $data['limit']   = $limit;
2166
 
2167
        return $data;
2168
    }
2169
 
2170
    // }}}
2171
    // {{{ outputBegin($command)
2172
 
2173
    /**
2174
     * Start output, HTML header etc
2175
     */
2176
    function outputBegin($command)
2177
    {
2178
        if (is_null($command)) {
2179
            // just the header
2180
            $tpl = $this->_initTemplate('header.inc.tpl.html');
2181
        } else {
2182
            $tpl = $this->_initTemplate('top.inc.tpl.html');
2183
            $tpl->setCurrentBlock('Search');
2184
            $tpl->parseCurrentBlock();
2185
 
2186
            if (!$this->_isProtected()) {
2187
                $tpl->setCurrentBlock('NotProtected');
2188
                $tpl->setVariable('Filler', ' ');
2189
                $tpl->parseCurrentBlock();
2190
            }
2191
        }
2192
 
2193
        // Initialise begin vars
2194
        if ($this->config->get('preferred_mirror') != $this->config->get('default_channel')) {
2195
            $mirror = ' (mirror ' .$this->config->get('preferred_mirror') . ')';
2196
        } else {
2197
            $mirror = '';
2198
        }
2199
        $tpl->setVariable('_default_channel', $this->config->get('default_channel') . $mirror);
2200
        $tpl->setVariable('ImgPEAR', $_SERVER['PHP_SELF'].'?img=pear');
2201
        $tpl->setVariable('Title', 'PEAR Package Manager, '.$command);
2202
        $tpl->setVariable('Headline', 'Webbased PEAR Package Manager on '.$_SERVER['SERVER_NAME']);
2203
 
2204
        $tpl->setCurrentBlock();
2205
 
2206
        $tpl->show();
2207
 
2208
        // submenu's for list, list-upgrades and list-all
2209
        if ($command == 'list' ||
2210
            $command == 'list-upgrades' ||
2211
            $command == 'list-all' ||
2212
            $command == 'list-categories' ||
2213
            $command == 'list-category' ||
2214
            $command == 'list-packages') {
2215
 
2216
            $tpl = $this->_initTemplate('package.submenu.tpl.html');
2217
 
2218
            $menus = array(
2219
                'list'              => 'list installed packages',
2220
                'list-upgrades'     => 'list available upgrades',
2221
                'list-packages'     => 'list all packagenames',
2222
                'list-categories'   => 'list all categories',
2223
            );
2224
            $highlight_map = array(
2225
                'list' => 'list',
2226
                'list-upgrades' => 'list-upgrades',
2227
                'list-all' => 'list-categories',
2228
                'list-categories' => 'list-categories',
2229
                'list-category' => 'list-category',
2230
                'list-packages' => 'list-packages',
2231
                    );
2232
            foreach ($menus as $name => $text) {
2233
                $tpl->setCurrentBlock('Submenu');
2234
                $tpl->setVariable("href", $_SERVER["PHP_SELF"].'?command='.$name);
2235
                $tpl->setVariable("text", $text);
2236
                if ($name == $highlight_map[$command]) {
2237
                    $tpl->setVariable("class", 'red');
2238
                } else {
2239
                    $tpl->setVariable("class", 'green');
2240
                }
2241
                $tpl->parseCurrentBlock();
2242
            }
2243
            $tpl->show();
2244
        }
2245
    }
2246
 
2247
    // }}}
2248
    // {{{ outputEnd($command)
2249
 
2250
    /**
2251
     * End output, HTML footer etc
2252
     */
2253
    function outputEnd($command)
2254
    {
2255
        if ($command == 'list') {
2256
            // show 'install package' footer
2257
            $tpl = $this->_initTemplate('package.manually.tpl.html');
2258
            $tpl->show();
2259
        }
2260
 
2261
        if (is_null($command)) {
2262
            // just the header
2263
            $tpl = $this->_initTemplate('footer.inc.tpl.html');
2264
        } else {
2265
            $tpl = $this->_initTemplate('bottom.inc.tpl.html');
2266
        }
2267
        $tpl->setVariable('Filler', '');
2268
        $tpl->show();
2269
    }
2270
 
2271
    // }}}
2272
 
2273
    /**
2274
     * Checks if this webfrontend is protected:
2275
     *  - when the client sais so
2276
     *  - when having .htaccess authentication
2277
     *
2278
     * @return boolean
2279
     */
2280
    function _isProtected()
2281
    {
2282
        if (isset($GLOBALS['_PEAR_Frontend_Web_protected']) &&
2283
              $GLOBALS['_PEAR_Frontend_Web_protected'] === true) {
2284
            return true;
2285
        }
2286
 
2287
        if (isset($_SERVER['PHP_AUTH_USER'])) {
2288
            return true;
2289
        }
2290
 
2291
        if (isset($_SERVER['AUTH_TYPE']) && !empty($_SERVER['AUTH_TYPE'])) {
2292
            return true;
2293
        }
2294
 
2295
        if (isset($_SERVER['PHP_AUTH_DIGEST']) && !empty($_SERVER['PHP_AUTH_DIGEST'])) {
2296
            return true;
2297
        }
2298
 
2299
        return false;
2300
    }
2301
 
2302
    /**
2303
     * Prepare packagename for HTML output:
2304
     * make it a link
2305
     *
2306
     * @param $package package name (evt 'chan/pkg')
2307
     * @param $channel channel name (when pkg not 'chan/pkg')
2308
     */
2309
    function _prepPkgName($package, $channel=null)
2310
    {
2311
        if (is_null($channel)) {
2312
            $full = $package;
2313
        } else {
2314
            $full = $channel.'/'.$package;
2315
        }
2316
 
2317
        return sprintf('<a href="%s?command=info&pkg=%s" class="blue">%s</a>',
2318
                            $_SERVER['PHP_SELF'],
2319
                            $full,
2320
                            $package);
2321
    }
2322
 
2323
    /**
2324
     * Prepare Icons (install/uninstall) for HTML output:
2325
     * make img and url
2326
     *
2327
     * @param $package package name
2328
     * @param $channel channel name
2329
     * @param $installed optional when we already know the package is installed
2330
     */
2331
    function _prepIcons($package_name, $channel, $installed=false)
2332
    {
2333
        $reg = $this->config->getRegistry();
2334
        $package = $channel.'/'.$package_name;
2335
 
2336
        if ($installed || $reg->packageExists($package_name, $channel)) {
2337
            if (in_array($package, $this->_no_delete_pkgs)) {
2338
                // don't allow to uninstall
2339
                $out = '&nbsp;';
2340
            } else {
2341
                $img = sprintf('<img src="%s?img=uninstall" width="18" height="17"  border="0" alt="uninstall">', $_SERVER["PHP_SELF"]);
2342
                $url = sprintf('%s?command=uninstall&pkg=%s', $_SERVER["PHP_SELF"], $package);
2343
                $out = sprintf('<a href="%s" onClick="return uninstallPkg(\'%s\');" id="%s">%s</a>', $url, $package, $package.'_href', $img);
2344
            }
2345
        } elseif (!$installed) {
2346
            $img = sprintf('<img src="%s?img=install" width="13" height="13"  border="0" alt="install">', $_SERVER["PHP_SELF"]);
2347
            $url = sprintf('%s?command=install&pkg=%s', $_SERVER["PHP_SELF"], $package);
2348
            $out = sprintf('<a href="%s" onClick="return installPkg(\'%s\');" id="%s">%s</a>', $url, $package, $package.'_href', $img);
2349
        }
2350
 
2351
        return $out;
2352
    }
2353
 
2354
    /**
2355
     * apply 'htmlentities' to every value of the array
2356
     * array_walk_recursive($array, 'htmlentities') in PHP5
2357
     */
2358
    function htmlentities_recursive($data) {
2359
        foreach($data as $key => $value) {
2360
            if (is_array($value)) {
2361
                $data[$key] = $this->htmlentities_recursive($value);
2362
            } else {
2363
                $data[$key] = htmlentities($value);
2364
            }
2365
        }
2366
        return $data;
2367
    }
2368
}
2369
 
2370
?>